1 00:00:17,940 --> 00:00:19,620 NEAL KEMP: Hi RailsConf. 2 00:00:19,620 --> 00:00:21,190 Today we're going to be talking about 3 00:00:21,190 --> 00:00:23,220 testing your services. 4 00:00:23,220 --> 00:00:24,330 But before we get into that, 5 00:00:24,330 --> 00:00:26,490 I want to introduce myself. 6 00:00:26,490 --> 00:00:29,200 My name's Neal. I'm originally from Iowa, 7 00:00:29,200 --> 00:00:32,320 so I feel at home here in the Midwest. 8 00:00:32,320 --> 00:00:35,380 Now I live in California, in LA specifically, 9 00:00:35,380 --> 00:00:36,870 and I'm a software developer and 10 00:00:36,870 --> 00:00:39,690 independent consultant who does Rails, 11 00:00:39,690 --> 00:00:42,050 JavaScript, HTML, CSS. 12 00:00:42,050 --> 00:00:43,340 Basically if you name an acronym 13 00:00:43,340 --> 00:00:46,129 I've probably coded in it at some point. 14 00:00:46,129 --> 00:00:49,710 So, today's talk is going to be the what, 15 00:00:49,710 --> 00:00:54,790 the why, and the how of testing your services. 16 00:00:54,790 --> 00:00:57,879 This is not a talk about building testable services. 17 00:00:57,879 --> 00:00:59,980 I could do an entire talk about that on 18 00:00:59,980 --> 00:01:04,290 its own. It's also not necessarily a talk about 19 00:01:04,290 --> 00:01:08,190 test-driven development. While I'm a practitioner, I don't think 20 00:01:08,190 --> 00:01:12,750 that the principles applied here correspond directly to test-driven 21 00:01:12,750 --> 00:01:14,800 or not test-driven development. 22 00:01:14,800 --> 00:01:15,940 [laughter] 23 00:01:15,940 --> 00:01:21,640 So. Got that one. Good. 24 00:01:21,640 --> 00:01:24,000 So first we're gonna talk about the what. So, 25 00:01:24,000 --> 00:01:26,280 we have to ask ourselves, what is a service. 26 00:01:26,280 --> 00:01:29,320 So I break it down into two main categories. 27 00:01:29,320 --> 00:01:31,760 First of all we have external services, like the 28 00:01:31,760 --> 00:01:37,550 Twitter API, Facebook's API, or Amazon Web Services. And 29 00:01:37,550 --> 00:01:41,810 the other category is internal software-oriented architecture, a buzz 30 00:01:41,810 --> 00:01:44,380 word we all know and love. 31 00:01:44,380 --> 00:01:47,940 So, basically for the purpose of this talk, it 32 00:01:47,940 --> 00:01:52,670 means anytime you're making an HTTP request to an 33 00:01:52,670 --> 00:01:57,410 endpoint in another repository. So, basically any network request 34 00:01:57,410 --> 00:02:01,250 you're making outside of your application. 35 00:02:01,250 --> 00:02:04,120 So now we're gonna talk about. Cause we need 36 00:02:04,120 --> 00:02:07,110 some justification before we go ahead and test all 37 00:02:07,110 --> 00:02:11,129 of our services without question. So, first we have 38 00:02:11,129 --> 00:02:13,530 to ask ourselves, why are services themselves important? I 39 00:02:13,530 --> 00:02:15,970 think a lot of these are pretty self-evident. It 40 00:02:15,970 --> 00:02:18,700 allows us to build things faster. It allows us 41 00:02:18,700 --> 00:02:22,050 to scale more easily. And we use them on 42 00:02:22,050 --> 00:02:25,330 basically every application. I don't think I can personally 43 00:02:25,330 --> 00:02:27,750 think of an app I've built in the past 44 00:02:27,750 --> 00:02:31,300 few years that hasn't glued on multiple services. 45 00:02:31,300 --> 00:02:33,410 And I'm also noticing that we're using more and 46 00:02:33,410 --> 00:02:38,030 more services for every application. So I would argue 47 00:02:38,030 --> 00:02:42,490 that services are critical to modern Rails development. So 48 00:02:42,490 --> 00:02:44,490 we have to ask ourselves then, why is testing 49 00:02:44,490 --> 00:02:47,800 those services important? Well, first of all, you should 50 00:02:47,800 --> 00:02:50,230 be testing everything else, so why would it be 51 00:02:50,230 --> 00:02:54,819 different for services? And services often compose critical features 52 00:02:54,819 --> 00:02:58,590 of your application. For example, a stripe integration. If 53 00:02:58,590 --> 00:03:00,200 your billing's down, you're gonna have a lot of 54 00:03:00,200 --> 00:03:04,400 issues. You know, if you have an API request 55 00:03:04,400 --> 00:03:06,550 to S3, you're not gonna be able to serve 56 00:03:06,550 --> 00:03:08,800 images, if that's down. 57 00:03:08,800 --> 00:03:11,230 And you might also encounter problems with these APIs. 58 00:03:11,230 --> 00:03:14,900 I know I sure have. Basically, any time I've 59 00:03:14,900 --> 00:03:18,550 worked with an API there's been some unexpected results. 60 00:03:18,550 --> 00:03:20,690 So the first example I'm gonna take you through 61 00:03:20,690 --> 00:03:24,480 is, you know, an internal API built by consultants 62 00:03:24,480 --> 00:03:26,180 in another part of the company. So this is 63 00:03:26,180 --> 00:03:30,500 the software-oriented architecture we're talking about. And they were 64 00:03:30,500 --> 00:03:33,819 exposing this API for our Rails app to consume, 65 00:03:33,819 --> 00:03:36,810 but we had issues all along the way, and 66 00:03:36,810 --> 00:03:41,250 it served to increase the project length significantly. Sometimes 67 00:03:41,250 --> 00:03:43,860 we'd have random null responses when we were supposed 68 00:03:43,860 --> 00:03:47,610 to get objects. There is random inconsistencies where we'd 69 00:03:47,610 --> 00:03:52,230 get weird symbols being printed out and different formatting. 70 00:03:52,230 --> 00:03:54,770 And in general it was a catastrophe. 71 00:03:54,770 --> 00:03:57,840 So it definitely lengthened the time to completion. And 72 00:03:57,840 --> 00:04:00,569 this was a lot due to a failure on 73 00:04:00,569 --> 00:04:03,560 our part to, you know, test the API thoroughly. 74 00:04:03,560 --> 00:04:05,980 So we couldn't express to them, you know, the 75 00:04:05,980 --> 00:04:07,560 problems we were having until we put it into 76 00:04:07,560 --> 00:04:10,300 production. So this is one problem that could have 77 00:04:10,300 --> 00:04:12,890 been solved by testing first. 78 00:04:12,890 --> 00:04:15,959 So, now we're gonna talk about a few problems 79 00:04:15,959 --> 00:04:18,269 I've had with external APIs. And I'm sure all 80 00:04:18,269 --> 00:04:21,899 of you have encountered similar issues with APIs in 81 00:04:21,899 --> 00:04:22,539 the past. 82 00:04:22,539 --> 00:04:25,539 So do we have any NHL fans in the, 83 00:04:25,539 --> 00:04:28,090 in the house here? Yeah? Chicago Black Hawks. Doing 84 00:04:28,090 --> 00:04:30,810 pretty well in the play-offs so far. We'll see 85 00:04:30,810 --> 00:04:32,990 how they go. I mean, obviously they're gonna get 86 00:04:32,990 --> 00:04:35,669 crushed by the Kings in a few rounds here, 87 00:04:35,669 --> 00:04:38,820 or the Sharks, possibly. But we'll see. I don't 88 00:04:38,820 --> 00:04:41,270 want to start a sports rivalry today. 89 00:04:41,270 --> 00:04:45,830 So you know, this basically ranged from small annoyances 90 00:04:45,830 --> 00:04:49,710 to, you know, major issues with this API. So 91 00:04:49,710 --> 00:04:52,620 we'd have annoyances like this, where some responses would 92 00:04:52,620 --> 00:04:55,370 come back with an id for the team, and 93 00:04:55,370 --> 00:04:57,180 others would come back with a code. And in 94 00:04:57,180 --> 00:04:59,550 this case, both of them refer to Anaheim. So 95 00:04:59,550 --> 00:05:01,490 this is a minor annoyance. You can code around 96 00:05:01,490 --> 00:05:02,050 that. 97 00:05:02,050 --> 00:05:06,139 Here, we have an undocumented bug, where basically the 98 00:05:06,139 --> 00:05:07,870 goals were all supposed to be as a part 99 00:05:07,870 --> 00:05:09,630 of an array, but if you only had one 100 00:05:09,630 --> 00:05:11,860 goal, it would be an object. And sadly we 101 00:05:11,860 --> 00:05:16,389 discovered this one in production, during a game. So 102 00:05:16,389 --> 00:05:18,060 that wasn't ideal. 103 00:05:18,060 --> 00:05:21,270 But, worst of all, after we had gone through 104 00:05:21,270 --> 00:05:24,270 all of the trouble of fixing these, we realized 105 00:05:24,270 --> 00:05:26,889 that there was no versioning on this API. So, 106 00:05:26,889 --> 00:05:30,250 even if we fixed it, we might be fixing 107 00:05:30,250 --> 00:05:35,240 it again a week later. So this is basically 108 00:05:35,240 --> 00:05:38,710 what it felt like to work with their API. 109 00:05:38,710 --> 00:05:41,740 So, another project I worked on, this is just 110 00:05:41,740 --> 00:05:44,389 kind of a fun side project, was a Snapchat 111 00:05:44,389 --> 00:05:47,580 API Client, so I could, you know, work with 112 00:05:47,580 --> 00:05:51,620 the Snapchat private API. And, well, one of these 113 00:05:51,620 --> 00:05:55,810 examples is extreme, in that there is haphazard documentation, 114 00:05:55,810 --> 00:05:59,240 or no documentation, in this case. I think we've 115 00:05:59,240 --> 00:06:03,919 all worked with APIs that have improper documentation. 116 00:06:03,919 --> 00:06:05,250 But in this case we didn't even know what 117 00:06:05,250 --> 00:06:07,240 the requests were, so we had to figure that 118 00:06:07,240 --> 00:06:11,240 out. There's also bizarre obfuscation implanted inside of the 119 00:06:11,240 --> 00:06:15,699 app itself that basically encrypted, on their iPhone, so 120 00:06:15,699 --> 00:06:19,009 people like me couldn't go in and build things 121 00:06:19,009 --> 00:06:21,169 like this. And there's a GitHub link if you're 122 00:06:21,169 --> 00:06:22,280 curious. 123 00:06:22,280 --> 00:06:25,530 So, now that we've talked a little bit about 124 00:06:25,530 --> 00:06:28,729 why it's important and outlined some of the problems 125 00:06:28,729 --> 00:06:31,290 you might encounter, we're gonna talk about how you're 126 00:06:31,290 --> 00:06:36,180 actually going to test these. 127 00:06:36,180 --> 00:06:38,240 So first we need to ask ourselves, what is 128 00:06:38,240 --> 00:06:43,100 different about services than regular code that we're testing? 129 00:06:43,100 --> 00:06:47,150 Well, first of all, we have external network requests 130 00:06:47,150 --> 00:06:49,800 that are being made, and second of all, you 131 00:06:49,800 --> 00:06:51,860 don't own the code, so you can't really do 132 00:06:51,860 --> 00:06:54,050 unit testing on it. It all has to be 133 00:06:54,050 --> 00:06:56,930 done from integration test perspective. 134 00:06:56,930 --> 00:07:01,930 So, what I propose for your tests, in general, 135 00:07:01,930 --> 00:07:05,820 is that you turn Airplane Mode on. This, I 136 00:07:05,820 --> 00:07:08,240 find, is the best way to think about your 137 00:07:08,240 --> 00:07:11,509 tests, because, first of all, failure is really bad 138 00:07:11,509 --> 00:07:14,680 in testing, and you shouldn't be making any, any 139 00:07:14,680 --> 00:07:16,820 network requests. 140 00:07:16,820 --> 00:07:18,770 So I think of this kind of in two 141 00:07:18,770 --> 00:07:20,889 ways. First of all, so it's Airplane Mode in 142 00:07:20,889 --> 00:07:23,300 the test mode so you can't do these things. 143 00:07:23,300 --> 00:07:24,960 But also it should be a test that you 144 00:07:24,960 --> 00:07:28,360 can run on an airplane. Basically meaning that if 145 00:07:28,360 --> 00:07:31,110 you're, you know, on a long trans-Atlantic flight or 146 00:07:31,110 --> 00:07:33,360 in the RailsConf lobby, you can still make your 147 00:07:33,360 --> 00:07:39,600 tests and, and they won't fail because of network 148 00:07:39,600 --> 00:07:42,180 issues. 149 00:07:42,180 --> 00:07:44,930 So this means you should not interact with your 150 00:07:44,930 --> 00:07:48,880 services from your testing environment. And we have a 151 00:07:48,880 --> 00:07:52,830 few caveats which I'll get into now. So, this 152 00:07:52,830 --> 00:07:56,770 includes dummy APIs. So there's some API makers that 153 00:07:56,770 --> 00:07:59,289 have their real API, and then they have a 154 00:07:59,289 --> 00:08:02,580 fake API which you can hit with requests, but 155 00:08:02,580 --> 00:08:05,729 it doesn't make any changes to your data. 156 00:08:05,729 --> 00:08:07,930 So you can't hit those, because those are somewhere 157 00:08:07,930 --> 00:08:11,199 else on the network. But I do allow you 158 00:08:11,199 --> 00:08:16,220 to make pre-recorded responses to those end points, and 159 00:08:16,220 --> 00:08:18,130 that means you can record them within your test 160 00:08:18,130 --> 00:08:19,919 suite, which we'll get into in a bit more 161 00:08:19,919 --> 00:08:21,530 detail later. 162 00:08:21,530 --> 00:08:25,300 So, for these examples, I'm going to be assuming 163 00:08:25,300 --> 00:08:29,479 that you're using Rails, obviously, and that you're using 164 00:08:29,479 --> 00:08:35,259 rspec for simplicities sake. So, it's time to stub 165 00:08:35,259 --> 00:08:36,919 out these requests. 166 00:08:36,919 --> 00:08:40,809 So, when you're stubbing an object, you're basically - 167 00:08:40,809 --> 00:08:43,039 for those who don't know - it's basically putting 168 00:08:43,039 --> 00:08:45,310 like a fake object in front of that object, 169 00:08:45,310 --> 00:08:47,880 so you're hitting that object instead of hitting the 170 00:08:47,880 --> 00:08:50,270 real one and, you know, saving time with, like 171 00:08:50,270 --> 00:08:53,790 setup processes and stuff like that. And we're doing 172 00:08:53,790 --> 00:08:56,370 a similar thing when you're stubbing a request to 173 00:08:56,370 --> 00:08:59,110 an endpoint, except we're saving a lot more time 174 00:08:59,110 --> 00:09:00,870 when we're doing so, because we don't have to 175 00:09:00,870 --> 00:09:04,490 make that additional network request. 176 00:09:04,490 --> 00:09:07,990 So there's some libraries that include built-in stubbing. So 177 00:09:07,990 --> 00:09:12,580 Typhoeus, if I pronounced that correctly, Faraday and Excon 178 00:09:12,580 --> 00:09:17,680 are three examples of pretty widely-used HTTP libraries built 179 00:09:17,680 --> 00:09:21,350 on top of net HTTP, I think, that have 180 00:09:21,350 --> 00:09:24,089 built-in stubbing functionality. 181 00:09:24,089 --> 00:09:26,690 But we can simplify this a little bit and 182 00:09:26,690 --> 00:09:29,399 use something called webmock, which I'm sure many of 183 00:09:29,399 --> 00:09:32,010 you have worked with in the past, which is 184 00:09:32,010 --> 00:09:35,880 a general purpose stubbing library for your test suite, 185 00:09:35,880 --> 00:09:39,870 so you don't have to learn each individual library's 186 00:09:39,870 --> 00:09:42,750 stubbing methods. 187 00:09:42,750 --> 00:09:44,600 So I'll take you through a quick example. Here 188 00:09:44,600 --> 00:09:48,870 is basic spec_helper. Nothing really interesting about this, except 189 00:09:48,870 --> 00:09:52,440 you have to include disable_net_connect! at the bottom. The 190 00:09:52,440 --> 00:09:57,110 rest is boilerplate. So I've highlighted that. And, obviously, 191 00:09:57,110 --> 00:09:58,880 with all of these examples, you should be putting 192 00:09:58,880 --> 00:10:02,180 the gem in your gem file and bundle installing 193 00:10:02,180 --> 00:10:04,310 before you start. 194 00:10:04,310 --> 00:10:06,930 So, when you put this in your code for 195 00:10:06,930 --> 00:10:09,510 the first time, you'll get a really great error 196 00:10:09,510 --> 00:10:11,620 with this, and I really like getting these errors, 197 00:10:11,620 --> 00:10:14,370 because it tells me exactly, in my code, where 198 00:10:14,370 --> 00:10:16,850 I'm making network requests. So if you're not already 199 00:10:16,850 --> 00:10:22,290 doing airplane mode tests, you should just plug this 200 00:10:22,290 --> 00:10:25,620 disable_net_connect! in, and then you'll get this error, which 201 00:10:25,620 --> 00:10:28,830 will tell you where you're making these network requests. 202 00:10:28,830 --> 00:10:31,220 And it also is really handy, and it gives 203 00:10:31,220 --> 00:10:33,810 you, actually, the request you're making at the bottom. 204 00:10:33,810 --> 00:10:37,680 So you can copy and paste that into your 205 00:10:37,680 --> 00:10:40,640 test in order to stub it automatically. And obviously 206 00:10:40,640 --> 00:10:42,880 you'll have to collect the body and the headers 207 00:10:42,880 --> 00:10:47,080 yourself, if you need to use those as well. 208 00:10:47,080 --> 00:10:51,570 So, for the following examples, we're gonna use probably 209 00:10:51,570 --> 00:10:57,670 the most, sorry, most simple FacebookWrapper ever invented. Basically, 210 00:10:57,670 --> 00:11:01,490 all we're doing here is sending a GET request 211 00:11:01,490 --> 00:11:06,269 to Facebook graph, the public API, for a user. 212 00:11:06,269 --> 00:11:08,029 And what this does is it just returns, like, 213 00:11:08,029 --> 00:11:11,260 very basic Facebook information about you. It has your 214 00:11:11,260 --> 00:11:15,050 Facebook username, your name, and an id and a 215 00:11:15,050 --> 00:11:17,010 few other fields. 216 00:11:17,010 --> 00:11:18,990 And then what we're doing with user_id up at 217 00:11:18,990 --> 00:11:22,740 the top is we are just pulling out the 218 00:11:22,740 --> 00:11:26,980 value for key_id. So this, all it does is 219 00:11:26,980 --> 00:11:33,060 return your Facebook id. Super, super simple. And make 220 00:11:33,060 --> 00:11:34,959 sure, since we're putting it in lib, that you 221 00:11:34,959 --> 00:11:38,279 require it at some point in your loading. 222 00:11:38,279 --> 00:11:40,930 So now we're gonna look at a test for 223 00:11:40,930 --> 00:11:43,130 this. So this is a test where we're not 224 00:11:43,130 --> 00:11:45,440 making a network request, but we're stubbing it out 225 00:11:45,440 --> 00:11:49,310 with webmock. So, at the bottom, you can see 226 00:11:49,310 --> 00:11:53,390 we're doing our testing case, and we're setting up 227 00:11:53,390 --> 00:11:57,769 an expectation that our user_id is equal to Arjun's 228 00:11:57,769 --> 00:12:00,890 user_id. And I'm using Arjun because he was the 229 00:12:00,890 --> 00:12:03,560 maker of the Facebook graph API wrapper. 230 00:12:03,560 --> 00:12:07,080 And, you can see, now, above, we are stubbing 231 00:12:07,080 --> 00:12:10,130 the request, just like you'd stub an object. We're 232 00:12:10,130 --> 00:12:13,380 stubbing the method of the HTTP request and then 233 00:12:13,380 --> 00:12:18,329 we're send, putting the link as the second argument. 234 00:12:18,329 --> 00:12:23,230 Next, we have to set up what it returns, 235 00:12:23,230 --> 00:12:26,700 and this is just an HTTP response that we're 236 00:12:26,700 --> 00:12:28,990 returning. So we want to put a status. 237 00:12:28,990 --> 00:12:32,560 You can set headers, which I generally don't do, 238 00:12:32,560 --> 00:12:35,420 but if you're doing any operations with the headers, 239 00:12:35,420 --> 00:12:40,670 you should definitely set up these in your responses. 240 00:12:40,670 --> 00:12:43,640 And the body, we have a really simple JSON 241 00:12:43,640 --> 00:12:46,670 string. I've cut out a few fields for brevity. 242 00:12:46,670 --> 00:12:49,170 But you can see it has an id, a 243 00:12:49,170 --> 00:12:51,380 first_name, and a username. 244 00:12:51,380 --> 00:12:54,649 So, this test will pass, and we're also making 245 00:12:54,649 --> 00:12:58,200 no net requests, work requests. So, the reasons it's 246 00:12:58,200 --> 00:13:01,730 better is it, first of all, it's faster, and 247 00:13:01,730 --> 00:13:04,019 we also aren't getting this intermittent failure that we 248 00:13:04,019 --> 00:13:09,110 were talking about earlier from the network request. 249 00:13:09,110 --> 00:13:12,920 So, that's a good general way, but there's ways 250 00:13:12,920 --> 00:13:15,200 we can also save time with this. So a 251 00:13:15,200 --> 00:13:19,459 lot of the really popular libraries for API wrappers 252 00:13:19,459 --> 00:13:24,220 also include mock-services within themselves or as an additional 253 00:13:24,220 --> 00:13:26,860 library on the side, and they use that for, 254 00:13:26,860 --> 00:13:29,649 you know, internal testing with their gems. So I 255 00:13:29,649 --> 00:13:32,450 recommend, if, if you can find one, to use 256 00:13:32,450 --> 00:13:34,860 this before you can go and use webmock, because 257 00:13:34,860 --> 00:13:36,040 it'll save you a lot of time. 258 00:13:36,040 --> 00:13:38,810 And I'll take you through a quick example. So 259 00:13:38,810 --> 00:13:44,959 we're gonna use Facebook graph mock here. And all 260 00:13:44,959 --> 00:13:48,370 we are doing is putting it into spec_helper. We're 261 00:13:48,370 --> 00:13:53,089 just including the methods and requiring it. Pretty straightforward. 262 00:13:53,089 --> 00:13:56,120 And now we're gonna look at a spec. 263 00:13:56,120 --> 00:14:00,670 So, basically, all we're doing is we're wrapping the 264 00:14:00,670 --> 00:14:05,190 test case within a wrapper that mocks out the 265 00:14:05,190 --> 00:14:07,829 request. So basically, all this one's doing is saying 266 00:14:07,829 --> 00:14:11,450 we're sending a git request to Facebook graph back 267 00:14:11,450 --> 00:14:14,519 slash Arjun, and then the third argument, in this 268 00:14:14,519 --> 00:14:20,190 case, is users/arjun_public, which is where the JSON file 269 00:14:20,190 --> 00:14:22,959 of this response is located in the gem. 270 00:14:22,959 --> 00:14:26,910 So, you can also specify your own responses, and 271 00:14:26,910 --> 00:14:29,850 I'd recommend you do that, because I found, actually, 272 00:14:29,850 --> 00:14:34,410 some issues with the Facebook graph mock mocking, like, 273 00:14:34,410 --> 00:14:38,670 responses, have some outdatedness in them. 274 00:14:38,670 --> 00:14:41,959 So, but this, you know, example, I'm not gonna 275 00:14:41,959 --> 00:14:43,610 take you through all of the gems that have 276 00:14:43,610 --> 00:14:46,290 this. But this can go to show that there 277 00:14:46,290 --> 00:14:49,730 are some benefits that you get from using this. 278 00:14:49,730 --> 00:14:51,600 It's already stubbed for you. You don't have to 279 00:14:51,600 --> 00:14:55,709 learn the API endpoints in order to use it, 280 00:14:55,709 --> 00:14:59,010 and some of these provide prerecorded responses for your 281 00:14:59,010 --> 00:15:01,149 use, so you don't have to go out and 282 00:15:01,149 --> 00:15:03,200 collect these. So it's just a good way of 283 00:15:03,200 --> 00:15:06,850 saving time, if you're using some popular libraries. 284 00:15:06,850 --> 00:15:10,779 Next, I'm going to take you through sham_rack, which 285 00:15:10,779 --> 00:15:14,000 is one of my more favorite ways of doing 286 00:15:14,000 --> 00:15:15,870 this. I kind of find this to be a 287 00:15:15,870 --> 00:15:20,490 fun way. Basically what sham_rock does, sorry, sham_rack does 288 00:15:20,490 --> 00:15:24,320 is it allows you to mount rack-based apps, which 289 00:15:24,320 --> 00:15:28,290 include Rails and Sinatra and others, and it allows 290 00:15:28,290 --> 00:15:33,519 you to make requests against these fake apps. 291 00:15:33,519 --> 00:15:36,510 So, in this case, we're going to get a 292 00:15:36,510 --> 00:15:39,769 little help from Sinatra in order to stub out 293 00:15:39,769 --> 00:15:45,550 these endpoints. So, spec_helper, the only thing interesting is 294 00:15:45,550 --> 00:15:50,360 that we leave in web-mock. Pretty boring there. But 295 00:15:50,360 --> 00:15:52,949 then we get to our fake. So I usually 296 00:15:52,949 --> 00:15:56,649 just put this spec/support and then fake whatever it 297 00:15:56,649 --> 00:15:59,089 is, in this case fake_facebook. 298 00:15:59,089 --> 00:16:01,370 And this just means it'll be loaded when you 299 00:16:01,370 --> 00:16:05,800 run your specs automatically. But it won't be, obviously, 300 00:16:05,800 --> 00:16:09,399 loaded into your production or staging environments, or development. 301 00:16:09,399 --> 00:16:12,000 So, in this case, at the top we can 302 00:16:12,000 --> 00:16:15,110 see, we're calling sham_rack, and we're setting up the 303 00:16:15,110 --> 00:16:17,139 endpoint which we're hitting against, which in this case 304 00:16:17,139 --> 00:16:20,380 is graph dot facebook dot com. And 433 is 305 00:16:20,380 --> 00:16:25,100 just specifying that we're using the HTTPS SSL link, 306 00:16:25,100 --> 00:16:27,010 and dot Sinatra just means we're going to be 307 00:16:27,010 --> 00:16:29,610 passing it in a Sinatra app. 308 00:16:29,610 --> 00:16:33,829 So, basically, contained within this block is a Sinatra 309 00:16:33,829 --> 00:16:35,990 app, and you can do virtually anything you can 310 00:16:35,990 --> 00:16:37,820 do with a regular Sinatra app, which is really 311 00:16:37,820 --> 00:16:41,010 cool. So you can just, you're just basically mounting 312 00:16:41,010 --> 00:16:43,920 this and testing against it. 313 00:16:43,920 --> 00:16:47,019 So, for those of you who don't use Sinatra 314 00:16:47,019 --> 00:16:50,610 very much, all we're doing here is specifying with 315 00:16:50,610 --> 00:16:53,630 the GET keyword that we're making a GET request 316 00:16:53,630 --> 00:16:57,519 to back slash something, and just like Rails, when 317 00:16:57,519 --> 00:17:00,889 you rake routes you'll see the parametrization of things 318 00:17:00,889 --> 00:17:02,680 with a colon before it. We're doing the exact 319 00:17:02,680 --> 00:17:04,959 same thing here with username. 320 00:17:04,959 --> 00:17:07,898 So, you'll see, in the middle, in the link 321 00:17:07,898 --> 00:17:10,740 we interpolate params username, and that's how you pull 322 00:17:10,740 --> 00:17:14,169 that out. So this is essentially just returning a 323 00:17:14,169 --> 00:17:17,919 string that is this response. You can obviously spice 324 00:17:17,919 --> 00:17:21,369 this up by setting status codes, adding conditionals in 325 00:17:21,369 --> 00:17:24,939 here if you need some more dynamic power, and 326 00:17:24,939 --> 00:17:28,580 also setting up the headers. And you can also, 327 00:17:28,580 --> 00:17:31,330 which I sometimes do this in my testing, is 328 00:17:31,330 --> 00:17:33,559 back it with like a small yml database, so 329 00:17:33,559 --> 00:17:36,309 you can get some more realistic data than just 330 00:17:36,309 --> 00:17:39,509 a simple string. 331 00:17:39,509 --> 00:17:46,470 So, that's the response. And. Now, when we're writing 332 00:17:46,470 --> 00:17:52,169 our spec for sham_rack, all we're doing is keeping 333 00:17:52,169 --> 00:17:53,779 it on this base level. We don't have to 334 00:17:53,779 --> 00:17:56,739 wrap it with anything, because it will automatically, in 335 00:17:56,739 --> 00:17:59,700 your tests, pick up the fact that you have 336 00:17:59,700 --> 00:18:02,710 sham_rack mounted, and it will automatically hit against that 337 00:18:02,710 --> 00:18:08,179 endpoint rather than hitting against the network. 338 00:18:08,179 --> 00:18:12,759 So, you might ask, why is this better? I 339 00:18:12,759 --> 00:18:14,879 think there are a few reasons. First, I find 340 00:18:14,879 --> 00:18:18,100 it more dynamic. I find it more expressive as 341 00:18:18,100 --> 00:18:20,429 well, and you can really add, you know, as 342 00:18:20,429 --> 00:18:24,179 much functionality you need to test your integrations as 343 00:18:24,179 --> 00:18:25,769 you want. And you can also back it with 344 00:18:25,769 --> 00:18:28,970 yml if you need, you know, some pre-population of, 345 00:18:28,970 --> 00:18:32,529 you know, real data. And it's also more readable. 346 00:18:32,529 --> 00:18:34,759 Let's go back to this for a second. And, 347 00:18:34,759 --> 00:18:37,479 you can see, like, reading through this is a 348 00:18:37,479 --> 00:18:39,340 lot easier to parse through, and you know where 349 00:18:39,340 --> 00:18:41,859 the API requests are being made to, versus the 350 00:18:41,859 --> 00:18:44,830 stubbing we showed in the first example, with web-mock, 351 00:18:44,830 --> 00:18:46,269 is a little bit hard to read. So that's 352 00:18:46,269 --> 00:18:48,859 why I prefer to use this. 353 00:18:48,859 --> 00:18:52,950 So next, we're going to talk about vcr, which 354 00:18:52,950 --> 00:18:55,299 is a pretty widely-used gem. And this one has 355 00:18:55,299 --> 00:18:58,379 some other benefits that I think are really important 356 00:18:58,379 --> 00:19:03,220 to use. Basically it prerecords your responses, and we'll 357 00:19:03,220 --> 00:19:05,320 take you through an example. 358 00:19:05,320 --> 00:19:10,049 So, spec_helper. The only thing interesting here. We have 359 00:19:10,049 --> 00:19:13,229 the vcr configuration block, and all we're doing is 360 00:19:13,229 --> 00:19:18,519 setting a cassette library. So that's basically where these 361 00:19:18,519 --> 00:19:21,029 responses will be saved. And then we're hooking into 362 00:19:21,029 --> 00:19:24,350 web-mock, because that's the stubbing library we're using. 363 00:19:24,350 --> 00:19:29,909 So, here's a spec. And as you can see, 364 00:19:29,909 --> 00:19:34,169 it's really, really similar to the Facebook graph mock. 365 00:19:34,169 --> 00:19:36,499 So basically what this does is, you're wrapping it 366 00:19:36,499 --> 00:19:40,509 in a block with vcr. So vcr, what it 367 00:19:40,509 --> 00:19:42,629 does, is it goes out to the network and 368 00:19:42,629 --> 00:19:46,009 makes the request for you, in your testing environment, 369 00:19:46,009 --> 00:19:48,659 and it pulls that response back and saves it, 370 00:19:48,659 --> 00:19:52,929 in this case, at Facebook user_arjun. 371 00:19:52,929 --> 00:19:54,369 And the nice thing about this is you don't 372 00:19:54,369 --> 00:19:58,090 have to go out and collect your own responses, 373 00:19:58,090 --> 00:19:59,669 which I find to be pretty tedious and also 374 00:19:59,669 --> 00:20:03,239 error prone. But, it also means you don't have 375 00:20:03,239 --> 00:20:08,499 to break airplane mode with your tests, because you 376 00:20:08,499 --> 00:20:11,070 can run this before, and you can cache all 377 00:20:11,070 --> 00:20:14,669 of the JSON responses and play them back in 378 00:20:14,669 --> 00:20:17,559 your build. So when you're running it on Travis 379 00:20:17,559 --> 00:20:20,009 EI or Circle or whatever you happen to use, 380 00:20:20,009 --> 00:20:23,369 you're not gonna break your build because of network 381 00:20:23,369 --> 00:20:27,789 failure. You're going to be using these cached responses. 382 00:20:27,789 --> 00:20:31,059 And that also just allows you to verify the 383 00:20:31,059 --> 00:20:33,679 responses. So, like I mentioned, it's a little error 384 00:20:33,679 --> 00:20:36,090 prone. I've tried collecting these responses on my own 385 00:20:36,090 --> 00:20:39,059 and, you know, sometimes I copy and paste them 386 00:20:39,059 --> 00:20:41,549 wrong and come up with an issue. So this 387 00:20:41,549 --> 00:20:43,580 kind of allows you to, like, have a nice 388 00:20:43,580 --> 00:20:46,929 programatic way of pulling those in. 389 00:20:46,929 --> 00:20:51,109 So, there's also an additional build process you can 390 00:20:51,109 --> 00:20:54,700 add. So, for the NHL example I talked about, 391 00:20:54,700 --> 00:20:56,590 the problem was there was no versioning. So what 392 00:20:56,590 --> 00:21:00,029 you can do is, if you want bonus points, 393 00:21:00,029 --> 00:21:03,080 and you are really dependent on an API that 394 00:21:03,080 --> 00:21:05,149 doesn't have versioning, you can do some kind of 395 00:21:05,149 --> 00:21:08,619 build process or, you know, test setup, where you're 396 00:21:08,619 --> 00:21:11,330 basically running it outside of your normal test mode, 397 00:21:11,330 --> 00:21:13,970 and you check the casettes for diffs, and verify 398 00:21:13,970 --> 00:21:17,070 that the responses are not changed from before. So 399 00:21:17,070 --> 00:21:19,029 this can help you avoid versioning issues. So I 400 00:21:19,029 --> 00:21:23,710 recommend that if you're using something like NHL API. 401 00:21:23,710 --> 00:21:26,940 So, the next one we're gonna briefly talk about 402 00:21:26,940 --> 00:21:31,200 is puffing-billy. And, aside from having a really cool 403 00:21:31,200 --> 00:21:34,989 name and a nice logo on their GitHub, this 404 00:21:34,989 --> 00:21:37,960 is an interesting gem to use. We're not gonna 405 00:21:37,960 --> 00:21:40,440 use an example here, but basically what it is 406 00:21:40,440 --> 00:21:44,590 is for in-browser requests. So basically if you're having 407 00:21:44,590 --> 00:21:49,720 integrations that are browser-based, you can record and reuse. 408 00:21:49,720 --> 00:21:54,509 Just like vcr, and use those responses again. 409 00:21:54,509 --> 00:21:58,639 So, I don't want you guys to think that 410 00:21:58,639 --> 00:22:00,429 all of this has to be done in Ruby, 411 00:22:00,429 --> 00:22:03,999 and that you have to use vcr to first 412 00:22:03,999 --> 00:22:06,379 record your responses. There's a lot of tools out 413 00:22:06,379 --> 00:22:11,489 there that will help you to collect these responses, 414 00:22:11,489 --> 00:22:13,940 test API endpoints faster, and I want to share 415 00:22:13,940 --> 00:22:17,259 some of those with you. 416 00:22:17,259 --> 00:22:21,509 So, Chrome Dev Tools. Has anyone heard of this 417 00:22:21,509 --> 00:22:24,830 in here? Yeah. Probably, probably all of you. But 418 00:22:24,830 --> 00:22:26,249 this is the first one I'm mentioning because I 419 00:22:26,249 --> 00:22:29,940 use it, probably every day. Obviously it gives you 420 00:22:29,940 --> 00:22:33,399 a really nice way of viewing responses and requests 421 00:22:33,399 --> 00:22:36,559 and resending them. So super useful. I'm not gonna 422 00:22:36,559 --> 00:22:38,259 get too far in-depth in that one because I'm 423 00:22:38,259 --> 00:22:41,139 assuming most people have worked with it. But it 424 00:22:41,139 --> 00:22:42,349 doesn't hurt to mention. 425 00:22:42,349 --> 00:22:45,590 So next, Postman. If you want to stay within 426 00:22:45,590 --> 00:22:48,889 Chrome. This is an extension you can use. And 427 00:22:48,889 --> 00:22:51,799 it basically gives you a user interface around running 428 00:22:51,799 --> 00:22:55,419 these requests so that you can have kind of 429 00:22:55,419 --> 00:22:57,879 an easier way to play with re, requests and 430 00:22:57,879 --> 00:23:00,179 responses. And it allows you save them. It gives 431 00:23:00,179 --> 00:23:04,729 you, you know, a time in milliseconds of completion. 432 00:23:04,729 --> 00:23:07,539 And this one I think is, I was working 433 00:23:07,539 --> 00:23:12,590 on a Tinder API Client for fun, so. That's 434 00:23:12,590 --> 00:23:15,299 what these requests are for. So, that one's actually 435 00:23:15,299 --> 00:23:17,729 up on my GitHub, too, if you're curious. 436 00:23:17,729 --> 00:23:20,419 So, I use that a lot. But if you 437 00:23:20,419 --> 00:23:23,519 like to stay command line based, I would recommend 438 00:23:23,519 --> 00:23:29,749 HTTPie. It's basically an easier-to-use version of curl, and 439 00:23:29,749 --> 00:23:31,970 it doesn't have, like, quite the archaic syntax curl 440 00:23:31,970 --> 00:23:35,259 has. So, I think it's, you know, worthy. Worthy 441 00:23:35,259 --> 00:23:37,519 of use. And, you know, it'd be easier, obviously, 442 00:23:37,519 --> 00:23:39,739 you know, to run a script around this than 443 00:23:39,739 --> 00:23:42,029 it would be to run it around Postman. So 444 00:23:42,029 --> 00:23:44,359 if you need to do something more programatic, this 445 00:23:44,359 --> 00:23:46,649 is probably your best option. 446 00:23:46,649 --> 00:23:50,340 And, one last tool I really like to use 447 00:23:50,340 --> 00:23:54,379 is called Charles. And Charles does a lot of 448 00:23:54,379 --> 00:23:57,289 the same things as Chrome Dev Tools does, but 449 00:23:57,289 --> 00:24:00,859 it acts as a proxy. So it basically captures, 450 00:24:00,859 --> 00:24:03,580 you know, requests between you and your network. So 451 00:24:03,580 --> 00:24:06,249 you can set this up to capture any request 452 00:24:06,249 --> 00:24:11,090 from your Mac machine, or you can proxy in 453 00:24:11,090 --> 00:24:13,969 your phone as well. So I found this really 454 00:24:13,969 --> 00:24:17,259 valuable when I was testing out the request from 455 00:24:17,259 --> 00:24:20,749 the Snapchat client, because it allowed me to see 456 00:24:20,749 --> 00:24:22,999 what my phone was making for requests and record 457 00:24:22,999 --> 00:24:25,489 those. And especially when we didn't know what the 458 00:24:25,489 --> 00:24:28,570 request was, it was very helpful in that case. 459 00:24:28,570 --> 00:24:31,690 And it's also cool because, you know, when you're 460 00:24:31,690 --> 00:24:35,759 building an API on Ruby and you want to 461 00:24:35,759 --> 00:24:37,969 build on iOS client with it, and you're not 462 00:24:37,969 --> 00:24:40,129 really sure how often to pull and stuff, I 463 00:24:40,129 --> 00:24:42,429 sometimes pull this up, and I'll just see what 464 00:24:42,429 --> 00:24:44,629 other apps are doing. So it's a good way 465 00:24:44,629 --> 00:24:47,340 of debugging other peoples work and, you know, seeing 466 00:24:47,340 --> 00:24:51,229 how they're doing it well. So, I highly recommend 467 00:24:51,229 --> 00:24:54,320 you check it out. It's pretty easy to use, 468 00:24:54,320 --> 00:24:57,440 and you can use it with SSL requests as 469 00:24:57,440 --> 00:24:57,979 well. 470 00:24:57,979 --> 00:25:00,840 So, here's some additional reading. I know you won't 471 00:25:00,840 --> 00:25:02,349 have time to write this all down. I'll post 472 00:25:02,349 --> 00:25:07,830 the slides on my Twitter. But, next up, let's 473 00:25:07,830 --> 00:25:09,719 bring it all together. 474 00:25:09,719 --> 00:25:12,690 So, we went over the what, the why, and 475 00:25:12,690 --> 00:25:16,450 the how of testing services. So, we've shown that 476 00:25:16,450 --> 00:25:19,830 testing services is crucial. They make up really important 477 00:25:19,830 --> 00:25:22,259 parts of your app, so skipping tests is pretty 478 00:25:22,259 --> 00:25:25,419 dangerous. I'd have to say, if you're in doubt, 479 00:25:25,419 --> 00:25:30,190 stub it out. Determine, when you're making choices between, 480 00:25:30,190 --> 00:25:35,109 you know, web-mock, sham_rack, or puffing-billy, even, you want 481 00:25:35,109 --> 00:25:37,679 to determine the amount of flexibility the need and 482 00:25:37,679 --> 00:25:40,190 the amount of extra work you're going to have. 483 00:25:40,190 --> 00:25:42,989 For example, it probably takes more time to make 484 00:25:42,989 --> 00:25:47,289 a sham_rack server and have dynamic responses than copying 485 00:25:47,289 --> 00:25:52,590 and pasting the request you get from the web-mock 486 00:25:52,590 --> 00:25:54,559 error. So, you kind of just need to look 487 00:25:54,559 --> 00:25:57,469 at the project you have and determine what use 488 00:25:57,469 --> 00:26:00,539 case best fits these options. 489 00:26:00,539 --> 00:26:04,629 And, also, record responses to save time. I wish 490 00:26:04,629 --> 00:26:06,590 I would have started doing this sooner. It's, like, 491 00:26:06,590 --> 00:26:11,330 super useful. I would highly recommend you do that. 492 00:26:11,330 --> 00:26:14,499 And next up, after me, I'd recommend you stick 493 00:26:14,499 --> 00:26:17,419 around. I had the pleasure of pairing with Austin 494 00:26:17,419 --> 00:26:20,840 yesterday, and I think his talk plays off my 495 00:26:20,840 --> 00:26:23,759 talk a lot, in that it talks a lot 496 00:26:23,759 --> 00:26:26,279 about inconsistent test failures. And he goes a lot 497 00:26:26,279 --> 00:26:29,539 more in-depth on, you know, other kinds of inconsistent 498 00:26:29,539 --> 00:26:33,249 test failures. And you just should definitely stick around 499 00:26:33,249 --> 00:26:35,210 if you have the time. 500 00:26:35,210 --> 00:26:37,969 So that's it for today. Thank you for taking 501 00:26:37,969 --> 00:26:40,619 the time to listen to my talk. And if 502 00:26:40,619 --> 00:26:42,519 I don't get to your question, feel free to 503 00:26:42,519 --> 00:26:44,450 shoot me an email, or if you just want 504 00:26:44,450 --> 00:26:46,299 to chat. And you can also find me on 505 00:26:46,299 --> 00:26:47,440 Twitter. So thanks a lot guys.