#100DaysOfWeb in Python Transcripts
Chapter: Days 81-84: Unit testing web apps
Lecture: Our first unit test
0:00 Now let's go write some tests. In fact, if we look over here we'll see there's already a test file in our project. Where did this come from?
0:08 Well this was created when we ran the cookiecutter to create the project long, long ago. And if you look at it, it's kind of, well
0:15 it's helpful, but it's really jamming way too many things together. So this says let's take all the possible types of tests
0:20 you might create for a pyramid and cram them into this place. So there's these view tests. These are what you would maybe do when you
0:28 try to call like this method here. And then there's functional tests which are, I would like to specify a URL and a status code
0:36 and then run that through the entire routing Pyramid infrastructure into your view method get the response, and then see what's happening.
0:44 So this is more of the functional tests and these are more of the direct view tests. And with this new concept of the view model we've added
0:51 we also need to have this idea of the view model tests. And the view model tests are going to look similar. So I'm going to copy that over here.
1:01 Although this part, this part is going to look different. Okay? So we have these three things. Now obviously, if you cram them all
1:08 into this one file in a real application it's going to be a thousand lines long. It's going to be very confusing
1:13 and you'll have lots of merge conflicts and all sorts of stuff. So this is not how we want to organize our code. So, lets' start working on that.
1:20 Create a package here called tests. And then in there we're going to create one for each of our main views. So we have a default set of views.
1:29 And we some about account, some about store. So each one of those we would create a folder or sub-package here.
1:36 This one called a default, so we'll stick with that. And then in here we're going to put the things associated with this.
1:42 So the view tests, called this default view tests. And we're also going to put another one in here called default view model tests.
1:52 That's one way to organize it. You can pick another. But something like this rather than all of it crammed into one file.
1:58 That would be no good. So let's go over here and work on the view model tests part first. See what we got. So we're importing unittest.
2:05 No, yeah could use pytest but this is what comes out of the pyramid cookiecutter. So we're going to use unittest.
2:11 Honestly, there's very little difference in a lot of use cases here. Now, this statement here is a little bit interesting
2:19 in then it's trying to do an import of views inside the function. So the idea is we're not even going to import the other code
2:25 that might interfere with like another test we've written. So instead of putting the imports up there
2:31 we do them down here at least in the view version. Okay, so what might we test here? Well let's test the index view model.
2:42 Now, we're going to need to import the view model to test it. And we're going to need to provide it a request.
2:48 Now remember, back over here, not that one. This one. To create one of these, we need to pass it a request
2:55 and a user ID. So let's try to make this work. So when I come over here I'm going to say our view model is going to be one of these.
3:03 Again we got to import this. I think it's okay to import it at the top. And it's going to want this dummy request.
3:09 So we're going to make a minor tweak there maybe. And then what else? We need to pass the user_id, we are using one for that.
3:17 Now what might we want to assert here? Well, there's couple of things. Some down here, let's go into it's place. Self.assert, now you're writing a test
3:25 we're going to have to assert various things. This value is equal to that. This thing is not None. This thing is None, and so on.
3:31 So first let's say that it's the case that there are no errors. So there error is None. And then, I'm going to say that the user is not None.
3:41 So we can assert those two things. We might also want to test something else but let's just go ahead and get this to work.
3:46 Now you'll see a little warning here and that's because we put this request and said it was a real request, not a dummy request.
3:54 So what we can do is we can just come over here and say this type is defined to be Pyramid request don't mess with us, we know it's going to work.
4:02 Now this looks like it's going to work. And it follows this cool pattern called the three A's of testing.
4:07 Which I like to write down when my tests are starting to look a little unclear or I'm kind of getting started. So the three A's of testing.
4:14 The first one is going to be arrange. So get everything set up. Then we're going to act. Now this creation, this object, does all of the validation.
4:23 So it's going to act. And the third part is the assert. So arrange, act and assert. This is what we want to do, but it turns out
4:30 that there's a challenge here. So we're going to try this but it's not going to work out so great.
4:34 If we go in here, you'll see it's going to call this function that's trying to go to the database. Do you think that's going to work?
4:40 Maybe, probably not so much actually. So let's just go and run this test right here. Actually this one.
4:47 I'm coming over here and if there's a test definition PyCharm will find it and say run the test for it.
4:51 We'll see a better way to centralize this in a second. But let's just run this. It looks like it worked, and then ugh, darn. No, what happened?
4:59 Well, come along here, and it said this didn't work. DBsession.factory calling that. Well how did that get set up? Let's look over here.
5:08 Well we called global_init. And we passed it all the database stuff and it created the database and validated it and connected to it.
5:15 Now I could go and actually call this function in our test setup. But we don't want to depend on the database.
5:21 What we want to do is test our view model. Test its validations and its interaction. It turns out we want someway to say do what you normally do
5:29 but don't actually talk to the database. So we need to do a little bit more work in order to make this actually run okay. And not talk to the database.
5:37 It's going to require a new concept but this is the test we pretty much have to write to test most of our view models.