 We're going to get started with Helen and managing mocks. Please give her a big round. Hi everybody, my name is Helen. I'm a freelance programmer. I've been using Python for quite a few years. This is my first year at Python. I'm really excited to be speaking here and I'm really enjoying Bill Bow and having a great week. So I decided to write this talk, I originally wrote it for Pycon UK last year I did that because, not because I felt like I was an expert on mocking, but because it was something that I'd tried working with quite a lot and I'd struggled with and felt like I was sort of hacking my way around and not really taking the time to understand it properly. Then I started a new project and it had lots of API interactions and databases that I didn't own and things that were quite a good case for mocking. And so I wanted to start doing things nicely and write lots of tests and try and understand this properly. So it's something that I've struggled with and learned a lot about and I wanted to share a few of the things I've learned. So what is a mock? A mock is a fake object that replaces a real object and the main use for this is in unit testing. Mocs are a way to control and isolate the environment in which your test runs. So why would you want this? First of all, you want your tests to be deterministic. If they are failing, it should be because there's something wrong with your code, not because of some external factor like a server being down. You need to be able to trust your tests. If you don't trust them, you'll start ignoring them. Mocing gives you more control over the inputs to your test. You can simulate different environments for your code and make sure it responds correctly to all kinds of scenarios. It's also fast. It's an in-memory operation. So it's generally quite a lot faster than the things it's replacing like network calls and file systems. And the speed of your tests is really important. Again, if that's too slow, you'll stop running them. I'm mostly going to be talking about the Moc library that comes with Python. This is called unittest.moc. Don't worry about the unit test name. You can use it with any framework. It works quite well with PyTest and other things. It used to be a standalone library. It was written by Michael Ford and it was brought into Python in 3.3. If you're using earlier versions, you can still use the standalone version and that's actually maintained and kept up to date. Python 3.3+, just do unittest.moc. Otherwise, pip installmoc and then importmoc. We're going to start with a look at Moc objects. You'll find yourself working with these quite a lot. You import Moc with a capital M and that's the Moc class. You set that up with whatever values you want it to have. Here I'm setting a value and then I can get that back as a property of the Moc. If you try to use a property that you haven't set, that's another Moc. If you try to use one of its properties, that's also another Moc. It's Mocs all the way down. You can dig down and set the values of these Mocs and get them back. Mocs are also callable and when you call a Moc, it returns another Moc. We've got more Mocs. If you want to change what your Moc returns, then you can set its return value and then when you call it, you'll get back the value that you set. You can dig down as far as you want into this structure. You can go as deep as you want and this is all about setting up the right environment for your code to pick up on. Another way that you can set up what your Moc does when it's called is side effects. A side effect can be an exception. If you assign an exception class to side effect on a Moc, then when that Moc is called, you'll get that exception raised. It can also be a function, so you can override the behavior of that. I don't find I use this a lot, but it is there if you need it. A side effect can also be a list of things you want to happen. This is useful if your code is going to be making multiple calls to this Moc and you want a different thing to happen each time. I can set up side effect with a value, an exception, and then another value. The first time I call it, I'll get the value. Second time, it will raise the exception. Third time, I'll get another value. If I try to call it again, I'll get a stop iteration because I ran out of side effects. If you want it to go on forever, it's just an iterable, so you can have a cycle or something. While you're doing things to Mocs, they are recording everything that's happening to them. All the calls that are made and all the arguments that are passed in, and you can query that information using these assertion calls. Most of them want you to say which arguments you expected them to be called with. We've got a cert called with, which looks at the last call that was made. It doesn't care what happened before that. You've got a cert called once with, which is the same, but it makes sure that it was only called once. You've got a cert any call, which just looks at whether that call was ever made with those arguments. It doesn't care about the others. You've got a cert has calls, which you can give it a list of calls and you can specify whether you care about the order. Then you've got a cert not called, which just you check that it wasn't called. You need to be a little bit careful with that last one, because so if you do this in Python 3.5, you create a mock, you call it, and then you assert that it wasn't called, you get an assertion error, and that's kind of what we might expect to happen. If you do the same thing in Python 3.4, you create the mock, you call it, you assert not called, and all that happens is that you get back another mock, and if that's in a test, it will just run and it won't fail. The reason for that is that a cert not called didn't exist before Python 3.5, so when we try to use it, it just behaves like anything that we might try to access on the mock. That just passes, and that's maybe a little bit dangerous. If you do plan to use that call, make sure you know which versions of Python people are going to be developing with, and maybe just don't if you can't. That's a little bit dangerous, and it has caught me out a couple of times, probably because I wasn't doing Red, Green, TDD properly, which is bad, but Python 3.5 thankfully does something about this. We get these safety checks if you try to call something beginning with assert, or a threat because you might make typos, it will complain. We've got assert called, which is being added in Python 3.6. We try to use that in Python 3.5, we get an attribute error, and that's kind of good because it's telling us that something's wrong with our code. If you really have things that are beginning with assert and you want to use them, then there's a flag called unsafe you can use to switch that off. Now, when you're using these assertion calls, you generally have to say which arguments you want to be passed in, you're expecting to be passed in, and they're generally fairly fancy about that, but sometimes you might not care about what one of the arguments was, maybe your argument's particularly complex, so you're testing them all in separate tests. So, you can use mock.ne for that, and you can just pass that in, pass it in as in place of an argument, and that just says I don't care what the value of this argument is. If you want even more control there, you can use comparison objects. So, these aren't really a special mock thing, they're just a nice Python thing with magic methods, so you might have been to other talks about this week. If you have an object, an instance of a class that implements the EQ magic method, then you can implement a custom comparison and pass that in as a check in your assertion checks. So, for example here, I'm checking whether my function was called with a multiple of five, and then with a multiple of four, and I've got a nicely formatted string to describe what went wrong as well. You can have even more control over the inspection of your calls. Maybe you want to work at a lower level, you can say, was this mock called, how many times was it called, and get access, raw access to all the arguments that it's called with. So, we've looked at a lot of features of mock objects. Let's have a look at how they fit into your tests. As a general kind of pattern, we'll be creating a mock and making sure it's in the right place, then we'll be setting up the values on it, the environment for your test, then we run the code under test, and then we check that our expectations have been met. So, first of all, let's look at how we get a mock into place. Now, for this, we use patch. So, this tells Python where to put a mock. You give it a path to a module, or a class, or a function, or anything that can be looked up as a path, and it will set things up so that when that path is looked up, it will give you back, rather than giving you back the real thing, it will give you back a mock, and you get access to that mock in your test. So, you can manipulate that mock and kind of get that injected into your code via patch. Now, the object it actually gives you is a magic mock, which is like a mock object, but it has some of the magic methods set up for convenience. We don't need to worry too much about that. So, there are a few different ways you can access patch, depending on what your situation is. First of all, we have a decorator. So, I've just got a little example function which I'm going to be testing. It uses requests to contact the GitHub API. It fetches a JSON document for a user and extracts that user's number of followers and returns it. So, it just looks like that when we run it. So, we patch our test method using request.get. We get a mock object passed into our test method as a parameter. We can then manipulate the values of the mock. So, we chain all the way down through return values and objects and more return values and set up what we're going to pretend is being returned from this API. And then we can run our assertion and check that the right value came back. You can also move it up to the top of your test class if you've got one and have it as a class decorator. If all your test methods are patching the same thing, then that's quite handy. You can stack multiple patches. You need to be careful about the order in which you do that. It kind of works from the inside out. So, the bottom most patch corresponds to the first parameter and so on. Patch can also be a context manager. So, we get a mock into our context and that survives the patches active for the lifetime of the context. So, this gives you more control over the lifetime of your mock if that's what you need. If you have any kind of clashes with other stuff that does clever things with parameters like pytest or other such things, that can be quite handy there. I tend to use the decorator version when I can because I don't like long lines of code and these make your code longer. Okay, so you can have even more control by calling start and stop on the object that returned by patch. I don't find that to use too much, but it can be useful. One thing I particularly have struggled with in mocking was patch paths and how look-ups work and what path to use when I'm patching. I often found that mocks weren't appearing where I was expecting them to and I was getting very confused. So, I just want to look at how this works. So, I've got my get-forwards function again and it's in a module called GithubUtils and I've put a test for that. So, the test imports GithubUtils. GithubUtils imports requests and pulls it into its own namespace. Coming back to our test, we patch requests.get. We get our mock, we manipulate it and then we call getFollowers. GetFollowers looks up requests.get. Because we patch that path, it will get back the mock. So, our test behaves as we might expect it to and it passes. If you consider a slightly different example where I've done a from request import get at the module level rather than looking up inside the function, the test is almost exactly the same apart from the import. So, if I import GithubUtils 2, that imports get from requests, then our test patches requests.get. It gets to the mock, manipulates it, calls getFollowers. GetFollowers called get. Get's already been looked up on requests and it was looked up before we patched. So, what's going to happen is we're going to get a slight delay and then we get something that doesn't match the value we set up. And that's because it was talking to the network because we patched. You might say we patched too soon. A better answer to that is that we patched the wrong thing. And this is how we fix that. We patch the thing that our module has already looked up. So, we patch it on the module itself because it owns a thing called get. So, our test looks like this and that works. The Python docs say ensure you patch the name used by the system under test. Another useful thing is patch.object. You can use this to attach a mock to another part of an object that you're already testing. For example, here I've got a simple greet function on my user class that says happy birthday to the user if it's a birthday. I'm testing that function and the mock is birthday. So, I get a user object, I patch it by passing in the object itself, the name of the method I want to patch and the return value I want it to have. And when I get inside that context and the user.isBirthday is a magic mock that will return true. So, that will make my test work. Mocking the time can be quite tricky. The date module is written in C so you can't mock individual bits of it. If you try, you'll probably get something like this. You can mock the whole thing, but it does mean you've got to chain all the way down to the bit you want and you don't get a choice at whether you're mocking the other bits. So, using another birthday-based method. So, I patch that. I modify the return value of today and that works. A possibly nicer way of doing that is the FreezeGun library, which is pretty cool. You pip install FreezeGun and it comes with a decorator called FreezeTime and that takes all sorts of interesting human-friendly formats that you can put in and you can have dates and date times and so on. It's pretty straightforward to use. I quite like that library. Mocking the file system is also quite tricky. There's a utility method called MockOpen which helps you out here. You give it a parameter called ReadData which you can tell it what data you want to pretend your file has and it will set up a special mock that has the right, all the right sort of file handled stuff. Because we're using Open, which is a built-in, we need to do something slightly different when we patch that and we need to use create equals true because we can't overwrite the built-in. We need to kind of create a local copy of Open that our code is going to pick up on. But then once we've got that, we can open and read our file. There's one little problem with this. You can't iterate over that file handle. Your file handling code probably has a nice pythonic interface like this. If you want that, then you've got to modify the mock that you get back from MockOpen and chain all the way down to the Ita magic method and set up the lines that you want. Note that if you're doing that in the context manager, you need to go through the Enter magic method as well. If you want to mock a property, so we've got our person class again. I've made his birthday a property now. If you try to patch the object, that doesn't work. You get this error. Not entirely sure why. I guess it's something to do with the way that properties work. You need special handling for that. For that, there's a parameter called new callable, which lets you say what type of mock you want to create. That's a special mock class called property mock set up just for this purpose. The other thing there is that you need to patch the class rather than the object, which might be a little bit limiting, but as far as I know, that's the only way to do that. I've just got a little example of a mock-based test. I've got this very crude retry function. You pass it another function, and it tries over and over to call it until it succeeds. If you get a database error, it will wait a little bit and then try again, and it will keep doubling that delay. When we're thinking about testing this, I can see two big reasons for mocking. First of all, we've got this time.sleep, which if it's in our test, then it's going to slow our test suite down. Secondly, we want to be able to simulate database errors. We don't want to cause rural database errors. This is a test that I've written for this function. We patch time.sleep, and that gets rid of the delays for us. We get a mock object passed in as our parameter, then we create another mock inside the function, and this is going to be the function that's going to be run each time, and we set it up with three side effects, two failures followed by a success. We call our retry function, and then we have a look at what happened. First, we check that it was called three times because we had two failures and then a success. Then mock.sleep assert has calls. We're just checking the calls, the delays that were made, and making sure that it was doubled each time. Then we check that the result that came back was what we set up as a return value for that function. That's just a little example for you. I'm nearly out of time, so I had some little bit of stuff about when you mock and why you should mock. I'm going to post these slides online afterwards and also got some recommended reading for you. A testing notebook by Harry Percival is very good and talks quite a lot about why you should mock and the advantages of mock and how it can help drive better design. Gary Bernhard Fast Test, Slow Test is a very good talk about the same sort of things. It's worth watching. The Unit Test Not Mock Library, I couldn't possibly cover every feature of mock in this time that I've tried, but it's a great read. I'm Helen Estee on Twitter and GitHub, and there's also a GitHub repository of IPython notebooks with this material. The slides are quite dense, so there's some interactive examples in there. Thank you. Great. Thanks very much. Please thank the speaker.