0:00:17.940,0:00:19.620 NEAL KEMP: Hi RailsConf. 0:00:19.620,0:00:21.190 Today we're going to be talking about 0:00:21.190,0:00:23.220 testing your services. 0:00:23.220,0:00:24.330 But before we get into that, 0:00:24.330,0:00:26.490 I want to introduce myself. 0:00:26.490,0:00:29.200 My name's Neal. I'm originally from Iowa, 0:00:29.200,0:00:32.320 so I feel at home here in the Midwest. 0:00:32.320,0:00:35.380 Now I live in California, in LA specifically, 0:00:35.380,0:00:36.870 and I'm a software developer and 0:00:36.870,0:00:39.690 independent consultant who does Rails, 0:00:39.690,0:00:42.050 JavaScript, HTML, CSS. 0:00:42.050,0:00:43.340 Basically if you name an acronym 0:00:43.340,0:00:46.129 I've probably coded in it at some point. 0:00:46.129,0:00:49.710 So, today's talk is going to be the what, 0:00:49.710,0:00:54.790 the why, and the how of testing your services. 0:00:54.790,0:00:57.879 This is not a talk about building testable[br]services. 0:00:57.879,0:00:59.980 I could do an entire talk about that on 0:00:59.980,0:01:04.290 its own. It's also not necessarily a talk[br]about 0:01:04.290,0:01:08.190 test-driven development. While I'm a practitioner,[br]I don't think 0:01:08.190,0:01:12.750 that the principles applied here correspond[br]directly to test-driven 0:01:12.750,0:01:14.800 or not test-driven development. 0:01:14.800,0:01:15.940 [laughter] 0:01:15.940,0:01:21.640 So. Got that one. Good. 0:01:21.640,0:01:24.000 So first we're gonna talk about the what.[br]So, 0:01:24.000,0:01:26.280 we have to ask ourselves, what is a service. 0:01:26.280,0:01:29.320 So I break it down into two main categories. 0:01:29.320,0:01:31.760 First of all we have external services, like[br]the 0:01:31.760,0:01:37.550 Twitter API, Facebook's API, or Amazon Web[br]Services. And 0:01:37.550,0:01:41.810 the other category is internal software-oriented[br]architecture, a buzz 0:01:41.810,0:01:44.380 word we all know and love. 0:01:44.380,0:01:47.940 So, basically for the purpose of this talk,[br]it 0:01:47.940,0:01:52.670 means anytime you're making an HTTP request[br]to an 0:01:52.670,0:01:57.410 endpoint in another repository. So, basically[br]any network request 0:01:57.410,0:02:01.250 you're making outside of your application. 0:02:01.250,0:02:04.120 So now we're gonna talk about. Cause we need 0:02:04.120,0:02:07.110 some justification before we go ahead and[br]test all 0:02:07.110,0:02:11.129 of our services without question. So, first[br]we have 0:02:11.129,0:02:13.530 to ask ourselves, why are services themselves[br]important? I 0:02:13.530,0:02:15.970 think a lot of these are pretty self-evident.[br]It 0:02:15.970,0:02:18.700 allows us to build things faster. It allows[br]us 0:02:18.700,0:02:22.050 to scale more easily. And we use them on 0:02:22.050,0:02:25.330 basically every application. I don't think[br]I can personally 0:02:25.330,0:02:27.750 think of an app I've built in the past 0:02:27.750,0:02:31.300 few years that hasn't glued on multiple services. 0:02:31.300,0:02:33.410 And I'm also noticing that we're using more[br]and 0:02:33.410,0:02:38.030 more services for every application. So I[br]would argue 0:02:38.030,0:02:42.490 that services are critical to modern Rails[br]development. So 0:02:42.490,0:02:44.490 we have to ask ourselves then, why is testing 0:02:44.490,0:02:47.800 those services important? Well, first of all,[br]you should 0:02:47.800,0:02:50.230 be testing everything else, so why would it[br]be 0:02:50.230,0:02:54.819 different for services? And services often[br]compose critical features 0:02:54.819,0:02:58.590 of your application. For example, a stripe[br]integration. If 0:02:58.590,0:03:00.200 your billing's down, you're gonna have a lot[br]of 0:03:00.200,0:03:04.400 issues. You know, if you have an API request 0:03:04.400,0:03:06.550 to S3, you're not gonna be able to serve 0:03:06.550,0:03:08.800 images, if that's down. 0:03:08.800,0:03:11.230 And you might also encounter problems with[br]these APIs. 0:03:11.230,0:03:14.900 I know I sure have. Basically, any time I've 0:03:14.900,0:03:18.550 worked with an API there's been some unexpected[br]results. 0:03:18.550,0:03:20.690 So the first example I'm gonna take you through 0:03:20.690,0:03:24.480 is, you know, an internal API built by consultants 0:03:24.480,0:03:26.180 in another part of the company. So this is 0:03:26.180,0:03:30.500 the software-oriented architecture we're talking[br]about. And they were 0:03:30.500,0:03:33.819 exposing this API for our Rails app to consume, 0:03:33.819,0:03:36.810 but we had issues all along the way, and 0:03:36.810,0:03:41.250 it served to increase the project length significantly.[br]Sometimes 0:03:41.250,0:03:43.860 we'd have random null responses when we were[br]supposed 0:03:43.860,0:03:47.610 to get objects. There is random inconsistencies[br]where we'd 0:03:47.610,0:03:52.230 get weird symbols being printed out and different[br]formatting. 0:03:52.230,0:03:54.770 And in general it was a catastrophe. 0:03:54.770,0:03:57.840 So it definitely lengthened the time to completion.[br]And 0:03:57.840,0:04:00.569 this was a lot due to a failure on 0:04:00.569,0:04:03.560 our part to, you know, test the API thoroughly. 0:04:03.560,0:04:05.980 So we couldn't express to them, you know,[br]the 0:04:05.980,0:04:07.560 problems we were having until we put it into 0:04:07.560,0:04:10.300 production. So this is one problem that could[br]have 0:04:10.300,0:04:12.890 been solved by testing first. 0:04:12.890,0:04:15.959 So, now we're gonna talk about a few problems 0:04:15.959,0:04:18.269 I've had with external APIs. And I'm sure[br]all 0:04:18.269,0:04:21.899 of you have encountered similar issues with[br]APIs in 0:04:21.899,0:04:22.539 the past. 0:04:22.539,0:04:25.539 So do we have any NHL fans in the, 0:04:25.539,0:04:28.090 in the house here? Yeah? Chicago Black Hawks.[br]Doing 0:04:28.090,0:04:30.810 pretty well in the play-offs so far. We'll[br]see 0:04:30.810,0:04:32.990 how they go. I mean, obviously they're gonna[br]get 0:04:32.990,0:04:35.669 crushed by the Kings in a few rounds here, 0:04:35.669,0:04:38.820 or the Sharks, possibly. But we'll see. I[br]don't 0:04:38.820,0:04:41.270 want to start a sports rivalry today. 0:04:41.270,0:04:45.830 So you know, this basically ranged from small[br]annoyances 0:04:45.830,0:04:49.710 to, you know, major issues with this API.[br]So 0:04:49.710,0:04:52.620 we'd have annoyances like this, where some[br]responses would 0:04:52.620,0:04:55.370 come back with an id for the team, and 0:04:55.370,0:04:57.180 others would come back with a code. And in 0:04:57.180,0:04:59.550 this case, both of them refer to Anaheim.[br]So 0:04:59.550,0:05:01.490 this is a minor annoyance. You can code around 0:05:01.490,0:05:02.050 that. 0:05:02.050,0:05:06.139 Here, we have an undocumented bug, where basically[br]the 0:05:06.139,0:05:07.870 goals were all supposed to be as a part 0:05:07.870,0:05:09.630 of an array, but if you only had one 0:05:09.630,0:05:11.860 goal, it would be an object. And sadly we 0:05:11.860,0:05:16.389 discovered this one in production, during[br]a game. So 0:05:16.389,0:05:18.060 that wasn't ideal. 0:05:18.060,0:05:21.270 But, worst of all, after we had gone through 0:05:21.270,0:05:24.270 all of the trouble of fixing these, we realized 0:05:24.270,0:05:26.889 that there was no versioning on this API.[br]So, 0:05:26.889,0:05:30.250 even if we fixed it, we might be fixing 0:05:30.250,0:05:35.240 it again a week later. So this is basically 0:05:35.240,0:05:38.710 what it felt like to work with their API. 0:05:38.710,0:05:41.740 So, another project I worked on, this is just 0:05:41.740,0:05:44.389 kind of a fun side project, was a Snapchat 0:05:44.389,0:05:47.580 API Client, so I could, you know, work with 0:05:47.580,0:05:51.620 the Snapchat private API. And, well, one of[br]these 0:05:51.620,0:05:55.810 examples is extreme, in that there is haphazard[br]documentation, 0:05:55.810,0:05:59.240 or no documentation, in this case. I think[br]we've 0:05:59.240,0:06:03.919 all worked with APIs that have improper documentation. 0:06:03.919,0:06:05.250 But in this case we didn't even know what 0:06:05.250,0:06:07.240 the requests were, so we had to figure that 0:06:07.240,0:06:11.240 out. There's also bizarre obfuscation implanted[br]inside of the 0:06:11.240,0:06:15.699 app itself that basically encrypted, on their[br]iPhone, so 0:06:15.699,0:06:19.009 people like me couldn't go in and build things 0:06:19.009,0:06:21.169 like this. And there's a GitHub link if you're 0:06:21.169,0:06:22.280 curious. 0:06:22.280,0:06:25.530 So, now that we've talked a little bit about 0:06:25.530,0:06:28.729 why it's important and outlined some of the[br]problems 0:06:28.729,0:06:31.290 you might encounter, we're gonna talk about[br]how you're 0:06:31.290,0:06:36.180 actually going to test these. 0:06:36.180,0:06:38.240 So first we need to ask ourselves, what is 0:06:38.240,0:06:43.100 different about services than regular code[br]that we're testing? 0:06:43.100,0:06:47.150 Well, first of all, we have external network[br]requests 0:06:47.150,0:06:49.800 that are being made, and second of all, you 0:06:49.800,0:06:51.860 don't own the code, so you can't really do 0:06:51.860,0:06:54.050 unit testing on it. It all has to be 0:06:54.050,0:06:56.930 done from integration test perspective. 0:06:56.930,0:07:01.930 So, what I propose for your tests, in general, 0:07:01.930,0:07:05.820 is that you turn Airplane Mode on. This, I 0:07:05.820,0:07:08.240 find, is the best way to think about your 0:07:08.240,0:07:11.509 tests, because, first of all, failure is really[br]bad 0:07:11.509,0:07:14.680 in testing, and you shouldn't be making any,[br]any 0:07:14.680,0:07:16.820 network requests. 0:07:16.820,0:07:18.770 So I think of this kind of in two 0:07:18.770,0:07:20.889 ways. First of all, so it's Airplane Mode[br]in 0:07:20.889,0:07:23.300 the test mode so you can't do these things. 0:07:23.300,0:07:24.960 But also it should be a test that you 0:07:24.960,0:07:28.360 can run on an airplane. Basically meaning[br]that if 0:07:28.360,0:07:31.110 you're, you know, on a long trans-Atlantic[br]flight or 0:07:31.110,0:07:33.360 in the RailsConf lobby, you can still make[br]your 0:07:33.360,0:07:39.600 tests and, and they won't fail because of[br]network 0:07:39.600,0:07:42.180 issues. 0:07:42.180,0:07:44.930 So this means you should not interact with[br]your 0:07:44.930,0:07:48.880 services from your testing environment. And[br]we have a 0:07:48.880,0:07:52.830 few caveats which I'll get into now. So, this 0:07:52.830,0:07:56.770 includes dummy APIs. So there's some API makers[br]that 0:07:56.770,0:07:59.289 have their real API, and then they have a 0:07:59.289,0:08:02.580 fake API which you can hit with requests,[br]but 0:08:02.580,0:08:05.729 it doesn't make any changes to your data. 0:08:05.729,0:08:07.930 So you can't hit those, because those are[br]somewhere 0:08:07.930,0:08:11.199 else on the network. But I do allow you 0:08:11.199,0:08:16.220 to make pre-recorded responses to those end[br]points, and 0:08:16.220,0:08:18.130 that means you can record them within your[br]test 0:08:18.130,0:08:19.919 suite, which we'll get into in a bit more 0:08:19.919,0:08:21.530 detail later. 0:08:21.530,0:08:25.300 So, for these examples, I'm going to be assuming 0:08:25.300,0:08:29.479 that you're using Rails, obviously, and that[br]you're using 0:08:29.479,0:08:35.259 rspec for simplicities sake. So, it's time[br]to stub 0:08:35.259,0:08:36.919 out these requests. 0:08:36.919,0:08:40.809 So, when you're stubbing an object, you're[br]basically - 0:08:40.809,0:08:43.039 for those who don't know - it's basically[br]putting 0:08:43.039,0:08:45.310 like a fake object in front of that object, 0:08:45.310,0:08:47.880 so you're hitting that object instead of hitting[br]the 0:08:47.880,0:08:50.270 real one and, you know, saving time with,[br]like 0:08:50.270,0:08:53.790 setup processes and stuff like that. And we're[br]doing 0:08:53.790,0:08:56.370 a similar thing when you're stubbing a request[br]to 0:08:56.370,0:08:59.110 an endpoint, except we're saving a lot more[br]time 0:08:59.110,0:09:00.870 when we're doing so, because we don't have[br]to 0:09:00.870,0:09:04.490 make that additional network request. 0:09:04.490,0:09:07.990 So there's some libraries that include built-in[br]stubbing. So 0:09:07.990,0:09:12.580 Typhoeus, if I pronounced that correctly,[br]Faraday and Excon 0:09:12.580,0:09:17.680 are three examples of pretty widely-used HTTP[br]libraries built 0:09:17.680,0:09:21.350 on top of net HTTP, I think, that have 0:09:21.350,0:09:24.089 built-in stubbing functionality. 0:09:24.089,0:09:26.690 But we can simplify this a little bit and 0:09:26.690,0:09:29.399 use something called webmock, which I'm sure[br]many of 0:09:29.399,0:09:32.010 you have worked with in the past, which is 0:09:32.010,0:09:35.880 a general purpose stubbing library for your[br]test suite, 0:09:35.880,0:09:39.870 so you don't have to learn each individual[br]library's 0:09:39.870,0:09:42.750 stubbing methods. 0:09:42.750,0:09:44.600 So I'll take you through a quick example.[br]Here 0:09:44.600,0:09:48.870 is basic spec_helper. Nothing really interesting[br]about this, except 0:09:48.870,0:09:52.440 you have to include disable_net_connect! at[br]the bottom. The 0:09:52.440,0:09:57.110 rest is boilerplate. So I've highlighted that.[br]And, obviously, 0:09:57.110,0:09:58.880 with all of these examples, you should be[br]putting 0:09:58.880,0:10:02.180 the gem in your gem file and bundle installing 0:10:02.180,0:10:04.310 before you start. 0:10:04.310,0:10:06.930 So, when you put this in your code for 0:10:06.930,0:10:09.510 the first time, you'll get a really great[br]error 0:10:09.510,0:10:11.620 with this, and I really like getting these[br]errors, 0:10:11.620,0:10:14.370 because it tells me exactly, in my code, where 0:10:14.370,0:10:16.850 I'm making network requests. So if you're[br]not already 0:10:16.850,0:10:22.290 doing airplane mode tests, you should just[br]plug this 0:10:22.290,0:10:25.620 disable_net_connect! in, and then you'll get[br]this error, which 0:10:25.620,0:10:28.830 will tell you where you're making these network[br]requests. 0:10:28.830,0:10:31.220 And it also is really handy, and it gives 0:10:31.220,0:10:33.810 you, actually, the request you're making at[br]the bottom. 0:10:33.810,0:10:37.680 So you can copy and paste that into your 0:10:37.680,0:10:40.640 test in order to stub it automatically. And[br]obviously 0:10:40.640,0:10:42.880 you'll have to collect the body and the headers 0:10:42.880,0:10:47.080 yourself, if you need to use those as well. 0:10:47.080,0:10:51.570 So, for the following examples, we're gonna[br]use probably 0:10:51.570,0:10:57.670 the most, sorry, most simple FacebookWrapper[br]ever invented. Basically, 0:10:57.670,0:11:01.490 all we're doing here is sending a GET request 0:11:01.490,0:11:06.269 to Facebook graph, the public API, for a user. 0:11:06.269,0:11:08.029 And what this does is it just returns, like, 0:11:08.029,0:11:11.260 very basic Facebook information about you.[br]It has your 0:11:11.260,0:11:15.050 Facebook username, your name, and an id and[br]a 0:11:15.050,0:11:17.010 few other fields. 0:11:17.010,0:11:18.990 And then what we're doing with user_id up[br]at 0:11:18.990,0:11:22.740 the top is we are just pulling out the 0:11:22.740,0:11:26.980 value for key_id. So this, all it does is 0:11:26.980,0:11:33.060 return your Facebook id. Super, super simple.[br]And make 0:11:33.060,0:11:34.959 sure, since we're putting it in lib, that[br]you 0:11:34.959,0:11:38.279 require it at some point in your loading. 0:11:38.279,0:11:40.930 So now we're gonna look at a test for 0:11:40.930,0:11:43.130 this. So this is a test where we're not 0:11:43.130,0:11:45.440 making a network request, but we're stubbing[br]it out 0:11:45.440,0:11:49.310 with webmock. So, at the bottom, you can see 0:11:49.310,0:11:53.390 we're doing our testing case, and we're setting[br]up 0:11:53.390,0:11:57.769 an expectation that our user_id is equal to[br]Arjun's 0:11:57.769,0:12:00.890 user_id. And I'm using Arjun because he was[br]the 0:12:00.890,0:12:03.560 maker of the Facebook graph API wrapper. 0:12:03.560,0:12:07.080 And, you can see, now, above, we are stubbing 0:12:07.080,0:12:10.130 the request, just like you'd stub an object.[br]We're 0:12:10.130,0:12:13.380 stubbing the method of the HTTP request and[br]then 0:12:13.380,0:12:18.329 we're send, putting the link as the second[br]argument. 0:12:18.329,0:12:23.230 Next, we have to set up what it returns, 0:12:23.230,0:12:26.700 and this is just an HTTP response that we're 0:12:26.700,0:12:28.990 returning. So we want to put a status. 0:12:28.990,0:12:32.560 You can set headers, which I generally don't[br]do, 0:12:32.560,0:12:35.420 but if you're doing any operations with the[br]headers, 0:12:35.420,0:12:40.670 you should definitely set up these in your[br]responses. 0:12:40.670,0:12:43.640 And the body, we have a really simple JSON 0:12:43.640,0:12:46.670 string. I've cut out a few fields for brevity. 0:12:46.670,0:12:49.170 But you can see it has an id, a 0:12:49.170,0:12:51.380 first_name, and a username. 0:12:51.380,0:12:54.649 So, this test will pass, and we're also making 0:12:54.649,0:12:58.200 no net requests, work requests. So, the reasons[br]it's 0:12:58.200,0:13:01.730 better is it, first of all, it's faster, and 0:13:01.730,0:13:04.019 we also aren't getting this intermittent failure[br]that we 0:13:04.019,0:13:09.110 were talking about earlier from the network[br]request. 0:13:09.110,0:13:12.920 So, that's a good general way, but there's[br]ways 0:13:12.920,0:13:15.200 we can also save time with this. So a 0:13:15.200,0:13:19.459 lot of the really popular libraries for API[br]wrappers 0:13:19.459,0:13:24.220 also include mock-services within themselves[br]or as an additional 0:13:24.220,0:13:26.860 library on the side, and they use that for, 0:13:26.860,0:13:29.649 you know, internal testing with their gems.[br]So I 0:13:29.649,0:13:32.450 recommend, if, if you can find one, to use 0:13:32.450,0:13:34.860 this before you can go and use webmock, because 0:13:34.860,0:13:36.040 it'll save you a lot of time. 0:13:36.040,0:13:38.810 And I'll take you through a quick example.[br]So 0:13:38.810,0:13:44.959 we're gonna use Facebook graph mock here.[br]And all 0:13:44.959,0:13:48.370 we are doing is putting it into spec_helper.[br]We're 0:13:48.370,0:13:53.089 just including the methods and requiring it.[br]Pretty straightforward. 0:13:53.089,0:13:56.120 And now we're gonna look at a spec. 0:13:56.120,0:14:00.670 So, basically, all we're doing is we're wrapping[br]the 0:14:00.670,0:14:05.190 test case within a wrapper that mocks out[br]the 0:14:05.190,0:14:07.829 request. So basically, all this one's doing[br]is saying 0:14:07.829,0:14:11.450 we're sending a git request to Facebook graph[br]back 0:14:11.450,0:14:14.519 slash Arjun, and then the third argument,[br]in this 0:14:14.519,0:14:20.190 case, is users/arjun_public, which is where[br]the JSON file 0:14:20.190,0:14:22.959 of this response is located in the gem. 0:14:22.959,0:14:26.910 So, you can also specify your own responses,[br]and 0:14:26.910,0:14:29.850 I'd recommend you do that, because I found,[br]actually, 0:14:29.850,0:14:34.410 some issues with the Facebook graph mock mocking,[br]like, 0:14:34.410,0:14:38.670 responses, have some outdatedness in them. 0:14:38.670,0:14:41.959 So, but this, you know, example, I'm not gonna 0:14:41.959,0:14:43.610 take you through all of the gems that have 0:14:43.610,0:14:46.290 this. But this can go to show that there 0:14:46.290,0:14:49.730 are some benefits that you get from using[br]this. 0:14:49.730,0:14:51.600 It's already stubbed for you. You don't have[br]to 0:14:51.600,0:14:55.709 learn the API endpoints in order to use it, 0:14:55.709,0:14:59.010 and some of these provide prerecorded responses[br]for your 0:14:59.010,0:15:01.149 use, so you don't have to go out and 0:15:01.149,0:15:03.200 collect these. So it's just a good way of 0:15:03.200,0:15:06.850 saving time, if you're using some popular[br]libraries. 0:15:06.850,0:15:10.779 Next, I'm going to take you through sham_rack,[br]which 0:15:10.779,0:15:14.000 is one of my more favorite ways of doing 0:15:14.000,0:15:15.870 this. I kind of find this to be a 0:15:15.870,0:15:20.490 fun way. Basically what sham_rock does, sorry,[br]sham_rack does 0:15:20.490,0:15:24.320 is it allows you to mount rack-based apps,[br]which 0:15:24.320,0:15:28.290 include Rails and Sinatra and others, and[br]it allows 0:15:28.290,0:15:33.519 you to make requests against these fake apps. 0:15:33.519,0:15:36.510 So, in this case, we're going to get a 0:15:36.510,0:15:39.769 little help from Sinatra in order to stub[br]out 0:15:39.769,0:15:45.550 these endpoints. So, spec_helper, the only[br]thing interesting is 0:15:45.550,0:15:50.360 that we leave in web-mock. Pretty boring there.[br]But 0:15:50.360,0:15:52.949 then we get to our fake. So I usually 0:15:52.949,0:15:56.649 just put this spec/support and then fake whatever[br]it 0:15:56.649,0:15:59.089 is, in this case fake_facebook. 0:15:59.089,0:16:01.370 And this just means it'll be loaded when you 0:16:01.370,0:16:05.800 run your specs automatically. But it won't[br]be, obviously, 0:16:05.800,0:16:09.399 loaded into your production or staging environments,[br]or development. 0:16:09.399,0:16:12.000 So, in this case, at the top we can 0:16:12.000,0:16:15.110 see, we're calling sham_rack, and we're setting[br]up the 0:16:15.110,0:16:17.139 endpoint which we're hitting against, which[br]in this case 0:16:17.139,0:16:20.380 is graph dot facebook dot com. And 433 is 0:16:20.380,0:16:25.100 just specifying that we're using the HTTPS[br]SSL link, 0:16:25.100,0:16:27.010 and dot Sinatra just means we're going to[br]be 0:16:27.010,0:16:29.610 passing it in a Sinatra app. 0:16:29.610,0:16:33.829 So, basically, contained within this block[br]is a Sinatra 0:16:33.829,0:16:35.990 app, and you can do virtually anything you[br]can 0:16:35.990,0:16:37.820 do with a regular Sinatra app, which is really 0:16:37.820,0:16:41.010 cool. So you can just, you're just basically[br]mounting 0:16:41.010,0:16:43.920 this and testing against it. 0:16:43.920,0:16:47.019 So, for those of you who don't use Sinatra 0:16:47.019,0:16:50.610 very much, all we're doing here is specifying[br]with 0:16:50.610,0:16:53.630 the GET keyword that we're making a GET request 0:16:53.630,0:16:57.519 to back slash something, and just like Rails,[br]when 0:16:57.519,0:17:00.889 you rake routes you'll see the parametrization[br]of things 0:17:00.889,0:17:02.680 with a colon before it. We're doing the exact 0:17:02.680,0:17:04.959 same thing here with username. 0:17:04.959,0:17:07.898 So, you'll see, in the middle, in the link 0:17:07.898,0:17:10.740 we interpolate params username, and that's[br]how you pull 0:17:10.740,0:17:14.169 that out. So this is essentially just returning[br]a 0:17:14.169,0:17:17.919 string that is this response. You can obviously[br]spice 0:17:17.919,0:17:21.369 this up by setting status codes, adding conditionals[br]in 0:17:21.369,0:17:24.939 here if you need some more dynamic power,[br]and 0:17:24.939,0:17:28.580 also setting up the headers. And you can also, 0:17:28.580,0:17:31.330 which I sometimes do this in my testing, is 0:17:31.330,0:17:33.559 back it with like a small yml database, so 0:17:33.559,0:17:36.309 you can get some more realistic data than[br]just 0:17:36.309,0:17:39.509 a simple string. 0:17:39.509,0:17:46.470 So, that's the response. And. Now, when we're[br]writing 0:17:46.470,0:17:52.169 our spec for sham_rack, all we're doing is[br]keeping 0:17:52.169,0:17:53.779 it on this base level. We don't have to 0:17:53.779,0:17:56.739 wrap it with anything, because it will automatically,[br]in 0:17:56.739,0:17:59.700 your tests, pick up the fact that you have 0:17:59.700,0:18:02.710 sham_rack mounted, and it will automatically[br]hit against that 0:18:02.710,0:18:08.179 endpoint rather than hitting against the network. 0:18:08.179,0:18:12.759 So, you might ask, why is this better? I 0:18:12.759,0:18:14.879 think there are a few reasons. First, I find 0:18:14.879,0:18:18.100 it more dynamic. I find it more expressive[br]as 0:18:18.100,0:18:20.429 well, and you can really add, you know, as 0:18:20.429,0:18:24.179 much functionality you need to test your integrations[br]as 0:18:24.179,0:18:25.769 you want. And you can also back it with 0:18:25.769,0:18:28.970 yml if you need, you know, some pre-population[br]of, 0:18:28.970,0:18:32.529 you know, real data. And it's also more readable. 0:18:32.529,0:18:34.759 Let's go back to this for a second. And, 0:18:34.759,0:18:37.479 you can see, like, reading through this is[br]a 0:18:37.479,0:18:39.340 lot easier to parse through, and you know[br]where 0:18:39.340,0:18:41.859 the API requests are being made to, versus[br]the 0:18:41.859,0:18:44.830 stubbing we showed in the first example, with[br]web-mock, 0:18:44.830,0:18:46.269 is a little bit hard to read. So that's 0:18:46.269,0:18:48.859 why I prefer to use this. 0:18:48.859,0:18:52.950 So next, we're going to talk about vcr, which 0:18:52.950,0:18:55.299 is a pretty widely-used gem. And this one[br]has 0:18:55.299,0:18:58.379 some other benefits that I think are really[br]important 0:18:58.379,0:19:03.220 to use. Basically it prerecords your responses,[br]and we'll 0:19:03.220,0:19:05.320 take you through an example. 0:19:05.320,0:19:10.049 So, spec_helper. The only thing interesting[br]here. We have 0:19:10.049,0:19:13.229 the vcr configuration block, and all we're[br]doing is 0:19:13.229,0:19:18.519 setting a cassette library. So that's basically[br]where these 0:19:18.519,0:19:21.029 responses will be saved. And then we're hooking[br]into 0:19:21.029,0:19:24.350 web-mock, because that's the stubbing library[br]we're using. 0:19:24.350,0:19:29.909 So, here's a spec. And as you can see, 0:19:29.909,0:19:34.169 it's really, really similar to the Facebook[br]graph mock. 0:19:34.169,0:19:36.499 So basically what this does is, you're wrapping[br]it 0:19:36.499,0:19:40.509 in a block with vcr. So vcr, what it 0:19:40.509,0:19:42.629 does, is it goes out to the network and 0:19:42.629,0:19:46.009 makes the request for you, in your testing[br]environment, 0:19:46.009,0:19:48.659 and it pulls that response back and saves[br]it, 0:19:48.659,0:19:52.929 in this case, at Facebook user_arjun. 0:19:52.929,0:19:54.369 And the nice thing about this is you don't 0:19:54.369,0:19:58.090 have to go out and collect your own responses, 0:19:58.090,0:19:59.669 which I find to be pretty tedious and also 0:19:59.669,0:20:03.239 error prone. But, it also means you don't[br]have 0:20:03.239,0:20:08.499 to break airplane mode with your tests, because[br]you 0:20:08.499,0:20:11.070 can run this before, and you can cache all 0:20:11.070,0:20:14.669 of the JSON responses and play them back in 0:20:14.669,0:20:17.559 your build. So when you're running it on Travis 0:20:17.559,0:20:20.009 EI or Circle or whatever you happen to use, 0:20:20.009,0:20:23.369 you're not gonna break your build because[br]of network 0:20:23.369,0:20:27.789 failure. You're going to be using these cached[br]responses. 0:20:27.789,0:20:31.059 And that also just allows you to verify the 0:20:31.059,0:20:33.679 responses. So, like I mentioned, it's a little[br]error 0:20:33.679,0:20:36.090 prone. I've tried collecting these responses[br]on my own 0:20:36.090,0:20:39.059 and, you know, sometimes I copy and paste[br]them 0:20:39.059,0:20:41.549 wrong and come up with an issue. So this 0:20:41.549,0:20:43.580 kind of allows you to, like, have a nice 0:20:43.580,0:20:46.929 programatic way of pulling those in. 0:20:46.929,0:20:51.109 So, there's also an additional build process[br]you can 0:20:51.109,0:20:54.700 add. So, for the NHL example I talked about, 0:20:54.700,0:20:56.590 the problem was there was no versioning. So[br]what 0:20:56.590,0:21:00.029 you can do is, if you want bonus points, 0:21:00.029,0:21:03.080 and you are really dependent on an API that 0:21:03.080,0:21:05.149 doesn't have versioning, you can do some kind[br]of 0:21:05.149,0:21:08.619 build process or, you know, test setup, where[br]you're 0:21:08.619,0:21:11.330 basically running it outside of your normal[br]test mode, 0:21:11.330,0:21:13.970 and you check the casettes for diffs, and[br]verify 0:21:13.970,0:21:17.070 that the responses are not changed from before.[br]So 0:21:17.070,0:21:19.029 this can help you avoid versioning issues.[br]So I 0:21:19.029,0:21:23.710 recommend that if you're using something like[br]NHL API. 0:21:23.710,0:21:26.940 So, the next one we're gonna briefly talk[br]about 0:21:26.940,0:21:31.200 is puffing-billy. And, aside from having a[br]really cool 0:21:31.200,0:21:34.989 name and a nice logo on their GitHub, this 0:21:34.989,0:21:37.960 is an interesting gem to use. We're not gonna 0:21:37.960,0:21:40.440 use an example here, but basically what it[br]is 0:21:40.440,0:21:44.590 is for in-browser requests. So basically if[br]you're having 0:21:44.590,0:21:49.720 integrations that are browser-based, you can[br]record and reuse. 0:21:49.720,0:21:54.509 Just like vcr, and use those responses again. 0:21:54.509,0:21:58.639 So, I don't want you guys to think that 0:21:58.639,0:22:00.429 all of this has to be done in Ruby, 0:22:00.429,0:22:03.999 and that you have to use vcr to first 0:22:03.999,0:22:06.379 record your responses. There's a lot of tools[br]out 0:22:06.379,0:22:11.489 there that will help you to collect these[br]responses, 0:22:11.489,0:22:13.940 test API endpoints faster, and I want to share 0:22:13.940,0:22:17.259 some of those with you. 0:22:17.259,0:22:21.509 So, Chrome Dev Tools. Has anyone heard of[br]this 0:22:21.509,0:22:24.830 in here? Yeah. Probably, probably all of you.[br]But 0:22:24.830,0:22:26.249 this is the first one I'm mentioning because[br]I 0:22:26.249,0:22:29.940 use it, probably every day. Obviously it gives[br]you 0:22:29.940,0:22:33.399 a really nice way of viewing responses and[br]requests 0:22:33.399,0:22:36.559 and resending them. So super useful. I'm not[br]gonna 0:22:36.559,0:22:38.259 get too far in-depth in that one because I'm 0:22:38.259,0:22:41.139 assuming most people have worked with it.[br]But it 0:22:41.139,0:22:42.349 doesn't hurt to mention. 0:22:42.349,0:22:45.590 So next, Postman. If you want to stay within 0:22:45.590,0:22:48.889 Chrome. This is an extension you can use.[br]And 0:22:48.889,0:22:51.799 it basically gives you a user interface around[br]running 0:22:51.799,0:22:55.419 these requests so that you can have kind of 0:22:55.419,0:22:57.879 an easier way to play with re, requests and 0:22:57.879,0:23:00.179 responses. And it allows you save them. It[br]gives 0:23:00.179,0:23:04.729 you, you know, a time in milliseconds of completion. 0:23:04.729,0:23:07.539 And this one I think is, I was working 0:23:07.539,0:23:12.590 on a Tinder API Client for fun, so. That's 0:23:12.590,0:23:15.299 what these requests are for. So, that one's[br]actually 0:23:15.299,0:23:17.729 up on my GitHub, too, if you're curious. 0:23:17.729,0:23:20.419 So, I use that a lot. But if you 0:23:20.419,0:23:23.519 like to stay command line based, I would recommend 0:23:23.519,0:23:29.749 HTTPie. It's basically an easier-to-use version[br]of curl, and 0:23:29.749,0:23:31.970 it doesn't have, like, quite the archaic syntax[br]curl 0:23:31.970,0:23:35.259 has. So, I think it's, you know, worthy. Worthy 0:23:35.259,0:23:37.519 of use. And, you know, it'd be easier, obviously, 0:23:37.519,0:23:39.739 you know, to run a script around this than 0:23:39.739,0:23:42.029 it would be to run it around Postman. So 0:23:42.029,0:23:44.359 if you need to do something more programatic,[br]this 0:23:44.359,0:23:46.649 is probably your best option. 0:23:46.649,0:23:50.340 And, one last tool I really like to use 0:23:50.340,0:23:54.379 is called Charles. And Charles does a lot[br]of 0:23:54.379,0:23:57.289 the same things as Chrome Dev Tools does,[br]but 0:23:57.289,0:24:00.859 it acts as a proxy. So it basically captures, 0:24:00.859,0:24:03.580 you know, requests between you and your network.[br]So 0:24:03.580,0:24:06.249 you can set this up to capture any request 0:24:06.249,0:24:11.090 from your Mac machine, or you can proxy in 0:24:11.090,0:24:13.969 your phone as well. So I found this really 0:24:13.969,0:24:17.259 valuable when I was testing out the request[br]from 0:24:17.259,0:24:20.749 the Snapchat client, because it allowed me[br]to see 0:24:20.749,0:24:22.999 what my phone was making for requests and[br]record 0:24:22.999,0:24:25.489 those. And especially when we didn't know[br]what the 0:24:25.489,0:24:28.570 request was, it was very helpful in that case. 0:24:28.570,0:24:31.690 And it's also cool because, you know, when[br]you're 0:24:31.690,0:24:35.759 building an API on Ruby and you want to 0:24:35.759,0:24:37.969 build on iOS client with it, and you're not 0:24:37.969,0:24:40.129 really sure how often to pull and stuff, I 0:24:40.129,0:24:42.429 sometimes pull this up, and I'll just see[br]what 0:24:42.429,0:24:44.629 other apps are doing. So it's a good way 0:24:44.629,0:24:47.340 of debugging other peoples work and, you know,[br]seeing 0:24:47.340,0:24:51.229 how they're doing it well. So, I highly recommend 0:24:51.229,0:24:54.320 you check it out. It's pretty easy to use, 0:24:54.320,0:24:57.440 and you can use it with SSL requests as 0:24:57.440,0:24:57.979 well. 0:24:57.979,0:25:00.840 So, here's some additional reading. I know[br]you won't 0:25:00.840,0:25:02.349 have time to write this all down. I'll post 0:25:02.349,0:25:07.830 the slides on my Twitter. But, next up, let's 0:25:07.830,0:25:09.719 bring it all together. 0:25:09.719,0:25:12.690 So, we went over the what, the why, and 0:25:12.690,0:25:16.450 the how of testing services. So, we've shown[br]that 0:25:16.450,0:25:19.830 testing services is crucial. They make up[br]really important 0:25:19.830,0:25:22.259 parts of your app, so skipping tests is pretty 0:25:22.259,0:25:25.419 dangerous. I'd have to say, if you're in doubt, 0:25:25.419,0:25:30.190 stub it out. Determine, when you're making[br]choices between, 0:25:30.190,0:25:35.109 you know, web-mock, sham_rack, or puffing-billy,[br]even, you want 0:25:35.109,0:25:37.679 to determine the amount of flexibility the[br]need and 0:25:37.679,0:25:40.190 the amount of extra work you're going to have. 0:25:40.190,0:25:42.989 For example, it probably takes more time to[br]make 0:25:42.989,0:25:47.289 a sham_rack server and have dynamic responses[br]than copying 0:25:47.289,0:25:52.590 and pasting the request you get from the web-mock 0:25:52.590,0:25:54.559 error. So, you kind of just need to look 0:25:54.559,0:25:57.469 at the project you have and determine what[br]use 0:25:57.469,0:26:00.539 case best fits these options. 0:26:00.539,0:26:04.629 And, also, record responses to save time.[br]I wish 0:26:04.629,0:26:06.590 I would have started doing this sooner. It's,[br]like, 0:26:06.590,0:26:11.330 super useful. I would highly recommend you[br]do that. 0:26:11.330,0:26:14.499 And next up, after me, I'd recommend you stick 0:26:14.499,0:26:17.419 around. I had the pleasure of pairing with[br]Austin 0:26:17.419,0:26:20.840 yesterday, and I think his talk plays off[br]my 0:26:20.840,0:26:23.759 talk a lot, in that it talks a lot 0:26:23.759,0:26:26.279 about inconsistent test failures. And he goes[br]a lot 0:26:26.279,0:26:29.539 more in-depth on, you know, other kinds of[br]inconsistent 0:26:29.539,0:26:33.249 test failures. And you just should definitely[br]stick around 0:26:33.249,0:26:35.210 if you have the time. 0:26:35.210,0:26:37.969 So that's it for today. Thank you for taking 0:26:37.969,0:26:40.619 the time to listen to my talk. And if 0:26:40.619,0:26:42.519 I don't get to your question, feel free to 0:26:42.519,0:26:44.450 shoot me an email, or if you just want 0:26:44.450,0:26:46.299 to chat. And you can also find me on 0:26:46.299,0:26:47.440 Twitter. So thanks a lot guys.