Building data-driven web apps with Flask and SQLAlchemy Transcripts
Chapter: Testing web apps
Lecture: Integrated tests
0:00 It's time to do a full test part of our application
0:02 the so-called integration test.
0:04 Where we fire up all of Flask, run all of our application
0:08 send a request through the Flask infrastructure
0:11 into our view methods, do the process in there
0:13 and get the result all the way back out.
0:15 And I'm going to do one test method here
0:18 a test of a single method here
0:20 so that you can see how it works.
0:21 We're going to test this index for the account.
0:24 So there's two scenarios.
0:25 One, if there is a user around
0:28 then they should be able to see their account page.
0:30 If they don't have a user logged in
0:32 remember, what it's going to do is, over here
0:34 it will redirect you to account/login.
0:36 So that's the kind of thing that we want to test
0:39 but we're going to do it in the full-featured way.
0:41 Now, how do we do that?
0:43 Let's go down here, I'm going to define another test method.
0:46 And I'm, did a little renaming here.
0:48 I started calling these tests test_vm
0:52 and then down here for just the views
0:54 test:v, then off test:int for integration
0:58 and then what we want to test is
0:59 account home, let's suppose you are not logged in.
1:05 Okay, so that's the test we are going to do first.
1:07 How do we do that?
1:08 Can we just go fire up, you now
1:10 import the app and call run?
1:12 No, it's not going work.
1:14 It'll actually really run flask, we don't want that.
1:17 So this is where our cool little fixture
1:19 our pi test fixture comes in.
1:21 So we're going to go over to this thing
1:23 and we're going to say that this here takes a client
1:28 and that corresponds this right here.
1:31 And what it does is, when you pass it as a variable
1:33 it's going to pass the return value, here, in there.
1:37 So we're going to go in and get our test client
1:40 from our flask_app and we're going to register the routes
1:43 the blueprints, set up the DB
1:45 maybe in the end we don't really want to use it
1:47 but sometimes you'll see we do want to use the database
1:50 and then we'll yield out a client here.
1:53 So then what we're just going to do
1:54 is something super super simple.
1:56 We're going to say a response
1:58 which is a response = client.get that's it.
2:03 What do you want to get slash account.
2:05 Which can get slash account.
2:07 Then we can make various assertions.
2:08 Like we can assert that response dot status code
2:13 is let's say, 200.
2:15 Now, is this going to work?
2:16 Is it going to let us go in there?
2:18 It's unlikely we're not going to be logged in
2:20 it should probably be a three or two redirect.
2:24 So let's just run this, see that's actually operates
2:27 gives us error and then we'll switch it over
2:28 to the right redirect code and check the location.
2:31 In order for this to work
2:32 we have to import client appear like so.
2:35 Alright. Let's run this again.
2:39 ohh, what did we get? There's an error.
2:42 It sent us a three or two that's a redirect code.
2:45 Where do they want us to redirect to?
2:47 Well that's kind of what we wanted.
2:48 So let's say this is task code direct two
2:50 and we'll say location is going to be
2:52 /account/login. This should pass. It doesn't.
2:58 What have I messed up here?
3:00 Ahh, HTTP localhost login, okay.
3:02 That's not quite what I was hoping for
3:05 but it's going to be just fine.
3:08 But that is the effect we were looking for.
3:10 Let's run one more time. There you go. Perfect.
3:14 So now we've done a test all the way through.
3:17 However, did that run, did that hit the database?
3:20 Well, no, but it might have.
3:22 It might have tried and why would it potentially try?
3:25 Because if we go over here
3:27 it's going to this IndexViewModel
3:29 which is going find user by user_id.
3:32 So I guess it probably did hit the database, yeah.
3:35 It didn't get a result back because we didn't pass
3:37 some kind of user_id but nonetheless
3:39 it probably did try to go to the database.
3:41 So here we need to mock this out
3:43 if we want to make that not happen.
3:45 So I guess the last thing that we should do here
3:47 is go ahead a do with unittest.mock.patch
3:54 target and return of value that is none.
3:58 And the target going to be, let's see
4:07 okay so this probably won't look any different to you
4:10 but the actual behavior is different. Let's do one more.
4:13 Let's supposed that we do want to test the case
4:15 when they have a login. Say with login.
4:19 So here what we want to do is create a test user
4:22 which is going to be a user and the name
4:26 is going to be Micheal and the email
4:29 is going to be firstname.lastname@example.org.
4:34 And so when they ask for the user
4:36 we're going to send back the test user
4:39 and we can go ahead and run this
4:40 this will fail because it's no longer redirect
4:43 fails because the left is 200, just like we hoped.
4:48 So we can again check that
4:50 but we can also check in data
4:53 we can go and assert that, something like Micheal
4:57 remember it says, "welcome Micheal" or something like that
4:59 is in response on data.
5:02 Now this gets a little trick cause that's binary
5:05 so we have to put a b here.
5:07 Let's give a shot and it still passes.
5:10 All right so these two right here show us
5:12 how we can use the client pytest fixture
5:15 to do integration testing with our app
5:18 and we can either as we saw in this first case
5:22 choose to let it hit the database
5:24 or if once we applied our mocking
5:27 and definitely here, once we applied our mocking
5:29 it actually no longer hit the database.
5:31 So most cases you don't want to let it hit the database
5:34 but when we get to this site map testing
5:37 you might actually want to let it do that there.