 Cześć wszystkim, moja nazwa jest Maciej Błańczyk. Zostałem tutaj w Polsce. Czasami pracuję na STX Next, który jest największy w Europie, a dzisiaj mówię o Mock & Patch, które pomagają nas, żeby stworzyć unie test w Pythonie. Więc powiedzmy, jak wiele ofi stworzy unie test, kiedy stworzyłeś twoje aplikacje? Powiedzmy, jak się stworzyłeś. Wow, prawie każdy, może nawet każdy. Wiesz, co jest Mock & Patch i jak używasz Mock & Patch w twoich unie testach? Dobra, więc prawie każdy. To będzie łatwiejsze, mówić o tym, kiedy wiesz to już. Przed moją prezentacją chciałbym odpowiedzieć na bardzo ważną pytanie. Dlaczego jesteśmy tutaj? My jesteśmy tutaj, ponieważ przygotowałem 12 Mockito drzwi, dla tych, które odpowiadają moje pytania, więc proszę, podczas prezentacją będę miał kilka pytań dla was. Proszę, żeby odpowiedzieć na te pytania, ponieważ nie chcę dodać 12 Mockito drzwi, po prezentacju przez mój sam. Więc to jest plan dla prezentacji. Najpierw pokażę wam klas, który będzie mój ekskurs, żeby stworzyć te unie testy podczas całego prezentacju. A potem mówię, co to jest Mockito drzwi i jak możemy to używać w naszym testie unii przez tę prezentacją. I w końcu mówię o tym, co to jest i jak można to używać w naszym przypadku. Więc powiedzmy, klient znał do nas i znalazł, żeby stworzyć aplikację, która będzie znalazła e-mails i z tych e-mails i znalazła to do końca używając REST API. Więc to wygląda na bardzo prostą aplikację. Powinniśmy, że zrobimy to. Znalazłyśmy nasz najlepszy sprzęt, znalazłem nich Ninja i po kilka dniach znalazły się klas, prawdopodobnie ten klas jest podobny do tego, message sender. Message sender ma ten method message as an argument. From message it takes sender, receiver and subject. And this data is being sent in few attempts by post method from request library. Actually three attempts are done. So depending on the result from post method from request library send method will return through or false depending on the result. So listen to you. What kind of unit test would you do for this send method? And this is worth Makito drink. Any ideas? Yes? Sorry? Of course. This is very important. But what other cases? Because this is basic. I think everyone would create a test like this. Exactly. Exception in this case would be raised by send method. Because we don't catch it. One of cases is to check if exception would be raised by this method. Second, I think the most important thing is just to check if we really send the correct data to the correct endpoint. Because we use post method. The main thing that this function does is sending data to the endpoint. So first of all we should check if hold this send method sends correct data to correct place. But when we execute all unit tests we don't want to send this fake test data to the real production endpoint. Because our client will not be happy of that. So when we check if this post method works correctly we also should not use the original implementation of post method. So first thing, check this but don't use the original post method. Second thing, yes check if exception raised by post method will be raised outside of the send function. What else? We have also yes, of course that's something that we need to check also. Yes, of course. We have some logic in our method. The logic is that we try to send data in few attempts. So I think we should also check if we really do it if in few attempts in case of failure we try to send this data. And last thing but not least we have message which is implemented somehow. So in unit test we should cut off from the original implementation of the message. So a lot of things to do let's see how we can do it. First we create message sender object then we get a fake message we will talk in a moment how we can get it. Next we try to send it and then we make some assertions for the result. How can we get a fake message? In this simple case we can just implement a new class inside of the message. We can just implement a new class inside our unit test with those three fields and that's all. It will work for now. But what if in few days from now someone will add a new field to our original message class or for example and I think this is more important someone will add a new method can't see there is no method inside but someone will add it. Then if we will go do this unit test we will need to extend it so we can fake this new method and actually also to check if this method was called correctly from the production code this is very important. So okay we can do it we will spend some time on it and after a few days probably a colleague will come to us and say wow nice code let's use it in other unit test so we will do it let's make it public so other ninja developers can use it and that's when we will notice that oh something like this already exists it's called mock so first thing I want you to remember from my presentation is that if you need to pass a fake object inside your production code and you can do it easily like in here we create fake message and you can easily pass it then use mock What is mock? I will show it because once everyone said that you use mocks so I will just show it this is how you create mock and on mock you can call anything anything that doesn't exist so if you do it for example not existing field you will always get value and if you call a method which doesn't exist you will also get some value this is very important because this is advantage and disadvantage both together but I will tell more about it later so for unit tests we don't want any value to be returned we want some value for example 5 like this we can assign value that we want a mock to return with this simple line and from this moment this value will be always returned by a mock this is simple version when you can do it in one line ok, how can we use it in our unit test? this is very simple in unit test we create a mock next we assign a value which we want it to return in production code the mock should be executed and in unit test, back in unit test you can make assertion if it was called correctly in this case our existing method was called only once and without an argument we can do it once with and if our method would be called with some kind of argument we can do it with the same assertion but we need to put the value that we expect to be called with there are more complex cases for example a method was called a few times with different arguments then we can use assert any call and of course in Python documentation you can find much more examples which I'm not able to show you i can show you just a few which I picked for example if we call directly a mock and then we call some methods on a mock we can use for example call arc list to check all the direct calls to the mock method calls to check calls to the methods defined on a mock all we can have all of them using mock calls in unit test we can use it in assertions but first we need to get a call object and we can compare existing calls with a list of expected call objects this is how we can use it in unit test so going back to our unit test we had to create a fake message we can do it like this this is a method which returns a fake of our message using a mock this mock defines receiver, sender and this will work at least for a few days so any ideas why this mock isn't the best mock that we can create and this is creation to get a moquito drink sorry exactly this is the problem so spets is almost what I was expecting to hear and the best answer is I will show it in a moment so what you said is that for example if someone will change the original message class for example removing the subject field and he will forget to remove it from the production code so it's still called in production code then our test will fail or not fail exactly the test will pass because you can call anything on a mock even if it doesn't exist and this is the problem and we can create mocs like this and spets is not enough in this case we can do much more we can do ah this is one more thing so I wanted to say that dragons will come in this case because we changed something in production code and our unit test passed so everything is green so we decided ok we can go to the production we can release our application and suddenly it appears after releasing our application doesn't work so it's much too late of course someone will say that we should use staging and other testing instances this is just an example that we change the code unit test passed but production code doesn't work dragons will come ok so the best mock which we could create in this case is with attribute code spetset and this will protect us from creating fakes of objects with fields or methods that doesn't exist in the real implementation in this case of message but what if a message is defined like this so all the fields are defined in init method and not on the class level can we use spetset in this case ok we unfortunately cannot use spetset in this case and this is also something that happens with response which is returned by post method response is defined in request library and we cannot control it but we would like in our unit test to control the status code we could do it with mock but the problem is that implementation of response looks like this so status code is defined in init method and not on the class level so we cannot use spetset to control when we want to create a mock of response we need to do something else and this is spets so spetset doesn't check if what we try to create with mock for example the status code exist in the implementation of the real class all what it does is checking if what we call from the production code was defined in the mock to the same but we get some protection it's not perfect but that's what we have to do ok so we already know how to mock the response we know how to mock the message now let's talk about the most important thing how to mock the post method because we don't want to send the test data to the real production endpoint as I said we should use mock when we can easily pass them or production code in this case we cannot do it easily it's somehow hard coded but message sender belongs to us so we can ask our ninja developers to change the source code and for example we can define sender in init method and in our test we can create a mock for our sender and everything will be fine but what if message sender would come from some kind of library but we still need to do this mock so this is the second thing I would like you to remember from my presentation use patch when you cannot easily pass the fake object patch will solve this problem how can we use a patch there are different ways of using patches I prefer using it as annotation to a test method and this is first option of the solution you can say with this string what should be patched and autospets equal true says that we want spetset attribute to be used patch will create a mock for this object and will pass it as an argument to our unit test and in here we can define what should be returned from our mock ok at the end of our unit test we can make assertions to our mock there is a second option of using patches and annotation and actually I prefer this solution because it doesn't take string it takes an object at least for the first argument and second argument can be also replaced by not string but I don't want to show it on the slide because it would be a little too complex so I prefer this solution because when I use IDE it supports me when I do some kind of refactoring with impulse and other things and in this case IDE would help me with fixing those impulse in case of strings it would not check anything when you create patch there is very important thing that patch created the patch should be created based on the place patch method this is something that you can forget when you create a patch for the first time we have almost two the same codes the code on the left we call post method from request and the code on the right we called post method from from something like message sender both post methods are actually the same they come from request library but the difference is in the way how they are called that we need to patch them differently on the left we patch post method from request on the right we patch post method from message sender this is very important you can forget about it when you create patches for the first time ok, we already know how to patch or maybe mock post method so now we can go to another thing how to make it to rise exception and to check if exception was riced we can do it simply of course with a patch and we can do it by assigning exception to a site effect attribute and in here we can check if exception was riced another thing we have post method called a few times if it's of course necessary and we would like to check if we really do it in our code so in case of failure when we try to send data for the first time we would like to check if our code tries to do it next time and next time so we need to be able to tell post method to return different things in our unit testing for different cause for example for first time return failure for second time return failure and for third time return success how can we do it of course we can do it with our patch and of course we can do it with site effect we just assign to site effect attribute i mean field a list of responses that we would like to be returned by this method and first value from the list will be returned for the first call second value for the second call and so on oryginal method and nothing else can work so in this case we can do it we can have our special implementation for example defined in our test and we can assign it with site effect instead of original implementation of our post method you mean this case or you mean arcs and quarks or yes to check the interface and existing fields this example it's not the best example some other example would be better for this case ok great yes so there are different ways for this people say different things exactly ok so i think this is the next slide sometimes we need to create a few patches to one unit test for example but you need to remember that the order of mocks which are passed to the unit test are opposite to the order of patches which annotates this method so first patch will return a mock which will be passed as the last one to the unit test and last patch will return a mock which will be passed as the first one to the test method which have the same patches so instead of repeating them all the time above each unit test you can just set it on the class level and this is very important you need to remember about this one before each test a setup method is called and after each test teach them method is called teach them is used to some clean up after the unit test and setup is used to prepare some environment for each unit test but people often forget that if setup will rise exception then unit test will never be executed and teach down also will never be executed so if someone will set a patch in setup method and will think that he can clean it in teach down and just after setting up a patch there will be exception rise in setup method then the teach down will never be called so if we made this mistake for example in first unit test and we execute one thousand unit test and two hundred first unit test is using this patch but this test doesn't know that it is using a patch it may fail and we will spend a lot of time to find out what happened so to solve this issue we should not use teach down we should use add clean up method like this and we will be protected from this problem ok and last thing i wanted to show you very simple and i think this maybe will make you to check the documentation for mox and patch because you can find a lot of interesting things there how we can simply mock environment variables with just one line like this using patch.dict ok to remind you to remember after my presentation first thing use mock when you can simply pass the fake object to production code and second thing use patches when you cannot simply pass the fake object to your production code any questions if you have yes is there a way here to use like the actual environment and just override a few keys not only with OS.env but also with any dictionary yes you can do it please please check the documentation you will see an example any more questions thank you it's more question theoretical you have some function and you want to test it and you mock stuff outside of this function and sometimes it's actually ugly you have few mox, you have defined side effects you define maybe something else you call arc list and other stuff is it any normal way how it's possible to make it look better suggestion at least you say you have a lot of mox with big setup with many side effects and everything in one unit test yes for example free for mox already looks like quite a lot ok so first of all try not to do this because it's too complex it will be very hard to analyze it try to make it more simple yes of course but how? it depends on the code i would have to see the code and maybe there would be a solution for this but of course not always it's possible ok any more questions yes when you are mentioning the common error when patching that you need to patch the word name is looked up by python isn't that a smell that you're coupling the implementation of the thing you're patching with your tests basically you need to go to the source of your library and check what they are doing and they might be changing it in minor patches because this is not necessarily public interface so making your code brittle yes very good question but i like it very much to show how we can check if exception was right i'm not saying that the code which i show you the production code was the best there are different ways for this and i think most of us will agree that we should catch this exception in our production code and pack it with our own implementation of exception for example and rise this exception and then we would catch our own exception and check this our own exception so we are not going down to the library which we use and i think this might be answer to the question am i correct ok anymore questions so i think less than 12 people were very active during my questions so please those people come to me and some other additional people please come also because i have 12 drinks and i don't want to drink them anymore questions so they are real drinks i just call them mojito because it sounds funny and it's almost close to mojito which actually they are so there are real drinks inside side effects depends on you if you are big then maybe side effects will not be so big yes exactly you have to test it ok