[Script Info] Title: [Events] Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text Dialogue: 0,0:00:17.94,0:00:19.62,Default,,0000,0000,0000,,NEAL KEMP: Hi RailsConf. Dialogue: 0,0:00:19.62,0:00:21.19,Default,,0000,0000,0000,,Today we're going to be talking about Dialogue: 0,0:00:21.19,0:00:23.22,Default,,0000,0000,0000,,testing your services. Dialogue: 0,0:00:23.22,0:00:24.33,Default,,0000,0000,0000,,But before we get into that, Dialogue: 0,0:00:24.33,0:00:26.49,Default,,0000,0000,0000,,I want to introduce myself. Dialogue: 0,0:00:26.49,0:00:29.20,Default,,0000,0000,0000,,My name's Neal. I'm originally from Iowa, Dialogue: 0,0:00:29.20,0:00:32.32,Default,,0000,0000,0000,,so I feel at home here in the Midwest. Dialogue: 0,0:00:32.32,0:00:35.38,Default,,0000,0000,0000,,Now I live in California, in LA specifically, Dialogue: 0,0:00:35.38,0:00:36.87,Default,,0000,0000,0000,,and I'm a software developer and Dialogue: 0,0:00:36.87,0:00:39.69,Default,,0000,0000,0000,,independent consultant who does Rails, Dialogue: 0,0:00:39.69,0:00:42.05,Default,,0000,0000,0000,,JavaScript, HTML, CSS. Dialogue: 0,0:00:42.05,0:00:43.34,Default,,0000,0000,0000,,Basically if you name an acronym Dialogue: 0,0:00:43.34,0:00:46.13,Default,,0000,0000,0000,,I've probably coded in it at some point. Dialogue: 0,0:00:46.13,0:00:49.71,Default,,0000,0000,0000,,So, today's talk is going to be the what, Dialogue: 0,0:00:49.71,0:00:54.79,Default,,0000,0000,0000,,the why, and the how of testing your services. Dialogue: 0,0:00:54.79,0:00:57.88,Default,,0000,0000,0000,,This is not a talk about building testable\Nservices. Dialogue: 0,0:00:57.88,0:00:59.98,Default,,0000,0000,0000,,I could do an entire talk about that on Dialogue: 0,0:00:59.98,0:01:04.29,Default,,0000,0000,0000,,its own. It's also not necessarily a talk\Nabout Dialogue: 0,0:01:04.29,0:01:08.19,Default,,0000,0000,0000,,test-driven development. While I'm a practitioner,\NI don't think Dialogue: 0,0:01:08.19,0:01:12.75,Default,,0000,0000,0000,,that the principles applied here correspond\Ndirectly to test-driven Dialogue: 0,0:01:12.75,0:01:14.80,Default,,0000,0000,0000,,or not test-driven development. Dialogue: 0,0:01:14.80,0:01:15.94,Default,,0000,0000,0000,,[laughter] Dialogue: 0,0:01:15.94,0:01:21.64,Default,,0000,0000,0000,,So. Got that one. Good. Dialogue: 0,0:01:21.64,0:01:24.00,Default,,0000,0000,0000,,So first we're gonna talk about the what.\NSo, Dialogue: 0,0:01:24.00,0:01:26.28,Default,,0000,0000,0000,,we have to ask ourselves, what is a service. Dialogue: 0,0:01:26.28,0:01:29.32,Default,,0000,0000,0000,,So I break it down into two main categories. Dialogue: 0,0:01:29.32,0:01:31.76,Default,,0000,0000,0000,,First of all we have external services, like\Nthe Dialogue: 0,0:01:31.76,0:01:37.55,Default,,0000,0000,0000,,Twitter API, Facebook's API, or Amazon Web\NServices. And Dialogue: 0,0:01:37.55,0:01:41.81,Default,,0000,0000,0000,,the other category is internal software-oriented\Narchitecture, a buzz Dialogue: 0,0:01:41.81,0:01:44.38,Default,,0000,0000,0000,,word we all know and love. Dialogue: 0,0:01:44.38,0:01:47.94,Default,,0000,0000,0000,,So, basically for the purpose of this talk,\Nit Dialogue: 0,0:01:47.94,0:01:52.67,Default,,0000,0000,0000,,means anytime you're making an HTTP request\Nto an Dialogue: 0,0:01:52.67,0:01:57.41,Default,,0000,0000,0000,,endpoint in another repository. So, basically\Nany network request Dialogue: 0,0:01:57.41,0:02:01.25,Default,,0000,0000,0000,,you're making outside of your application. Dialogue: 0,0:02:01.25,0:02:04.12,Default,,0000,0000,0000,,So now we're gonna talk about. Cause we need Dialogue: 0,0:02:04.12,0:02:07.11,Default,,0000,0000,0000,,some justification before we go ahead and\Ntest all Dialogue: 0,0:02:07.11,0:02:11.13,Default,,0000,0000,0000,,of our services without question. So, first\Nwe have Dialogue: 0,0:02:11.13,0:02:13.53,Default,,0000,0000,0000,,to ask ourselves, why are services themselves\Nimportant? I Dialogue: 0,0:02:13.53,0:02:15.97,Default,,0000,0000,0000,,think a lot of these are pretty self-evident.\NIt Dialogue: 0,0:02:15.97,0:02:18.70,Default,,0000,0000,0000,,allows us to build things faster. It allows\Nus Dialogue: 0,0:02:18.70,0:02:22.05,Default,,0000,0000,0000,,to scale more easily. And we use them on Dialogue: 0,0:02:22.05,0:02:25.33,Default,,0000,0000,0000,,basically every application. I don't think\NI can personally Dialogue: 0,0:02:25.33,0:02:27.75,Default,,0000,0000,0000,,think of an app I've built in the past Dialogue: 0,0:02:27.75,0:02:31.30,Default,,0000,0000,0000,,few years that hasn't glued on multiple services. Dialogue: 0,0:02:31.30,0:02:33.41,Default,,0000,0000,0000,,And I'm also noticing that we're using more\Nand Dialogue: 0,0:02:33.41,0:02:38.03,Default,,0000,0000,0000,,more services for every application. So I\Nwould argue Dialogue: 0,0:02:38.03,0:02:42.49,Default,,0000,0000,0000,,that services are critical to modern Rails\Ndevelopment. So Dialogue: 0,0:02:42.49,0:02:44.49,Default,,0000,0000,0000,,we have to ask ourselves then, why is testing Dialogue: 0,0:02:44.49,0:02:47.80,Default,,0000,0000,0000,,those services important? Well, first of all,\Nyou should Dialogue: 0,0:02:47.80,0:02:50.23,Default,,0000,0000,0000,,be testing everything else, so why would it\Nbe Dialogue: 0,0:02:50.23,0:02:54.82,Default,,0000,0000,0000,,different for services? And services often\Ncompose critical features Dialogue: 0,0:02:54.82,0:02:58.59,Default,,0000,0000,0000,,of your application. For example, a stripe\Nintegration. If Dialogue: 0,0:02:58.59,0:03:00.20,Default,,0000,0000,0000,,your billing's down, you're gonna have a lot\Nof Dialogue: 0,0:03:00.20,0:03:04.40,Default,,0000,0000,0000,,issues. You know, if you have an API request Dialogue: 0,0:03:04.40,0:03:06.55,Default,,0000,0000,0000,,to S3, you're not gonna be able to serve Dialogue: 0,0:03:06.55,0:03:08.80,Default,,0000,0000,0000,,images, if that's down. Dialogue: 0,0:03:08.80,0:03:11.23,Default,,0000,0000,0000,,And you might also encounter problems with\Nthese APIs. Dialogue: 0,0:03:11.23,0:03:14.90,Default,,0000,0000,0000,,I know I sure have. Basically, any time I've Dialogue: 0,0:03:14.90,0:03:18.55,Default,,0000,0000,0000,,worked with an API there's been some unexpected\Nresults. Dialogue: 0,0:03:18.55,0:03:20.69,Default,,0000,0000,0000,,So the first example I'm gonna take you through Dialogue: 0,0:03:20.69,0:03:24.48,Default,,0000,0000,0000,,is, you know, an internal API built by consultants Dialogue: 0,0:03:24.48,0:03:26.18,Default,,0000,0000,0000,,in another part of the company. So this is Dialogue: 0,0:03:26.18,0:03:30.50,Default,,0000,0000,0000,,the software-oriented architecture we're talking\Nabout. And they were Dialogue: 0,0:03:30.50,0:03:33.82,Default,,0000,0000,0000,,exposing this API for our Rails app to consume, Dialogue: 0,0:03:33.82,0:03:36.81,Default,,0000,0000,0000,,but we had issues all along the way, and Dialogue: 0,0:03:36.81,0:03:41.25,Default,,0000,0000,0000,,it served to increase the project length significantly.\NSometimes Dialogue: 0,0:03:41.25,0:03:43.86,Default,,0000,0000,0000,,we'd have random null responses when we were\Nsupposed Dialogue: 0,0:03:43.86,0:03:47.61,Default,,0000,0000,0000,,to get objects. There is random inconsistencies\Nwhere we'd Dialogue: 0,0:03:47.61,0:03:52.23,Default,,0000,0000,0000,,get weird symbols being printed out and different\Nformatting. Dialogue: 0,0:03:52.23,0:03:54.77,Default,,0000,0000,0000,,And in general it was a catastrophe. Dialogue: 0,0:03:54.77,0:03:57.84,Default,,0000,0000,0000,,So it definitely lengthened the time to completion.\NAnd Dialogue: 0,0:03:57.84,0:04:00.57,Default,,0000,0000,0000,,this was a lot due to a failure on Dialogue: 0,0:04:00.57,0:04:03.56,Default,,0000,0000,0000,,our part to, you know, test the API thoroughly. Dialogue: 0,0:04:03.56,0:04:05.98,Default,,0000,0000,0000,,So we couldn't express to them, you know,\Nthe Dialogue: 0,0:04:05.98,0:04:07.56,Default,,0000,0000,0000,,problems we were having until we put it into Dialogue: 0,0:04:07.56,0:04:10.30,Default,,0000,0000,0000,,production. So this is one problem that could\Nhave Dialogue: 0,0:04:10.30,0:04:12.89,Default,,0000,0000,0000,,been solved by testing first. Dialogue: 0,0:04:12.89,0:04:15.96,Default,,0000,0000,0000,,So, now we're gonna talk about a few problems Dialogue: 0,0:04:15.96,0:04:18.27,Default,,0000,0000,0000,,I've had with external APIs. And I'm sure\Nall Dialogue: 0,0:04:18.27,0:04:21.90,Default,,0000,0000,0000,,of you have encountered similar issues with\NAPIs in Dialogue: 0,0:04:21.90,0:04:22.54,Default,,0000,0000,0000,,the past. Dialogue: 0,0:04:22.54,0:04:25.54,Default,,0000,0000,0000,,So do we have any NHL fans in the, Dialogue: 0,0:04:25.54,0:04:28.09,Default,,0000,0000,0000,,in the house here? Yeah? Chicago Black Hawks.\NDoing Dialogue: 0,0:04:28.09,0:04:30.81,Default,,0000,0000,0000,,pretty well in the play-offs so far. We'll\Nsee Dialogue: 0,0:04:30.81,0:04:32.99,Default,,0000,0000,0000,,how they go. I mean, obviously they're gonna\Nget Dialogue: 0,0:04:32.99,0:04:35.67,Default,,0000,0000,0000,,crushed by the Kings in a few rounds here, Dialogue: 0,0:04:35.67,0:04:38.82,Default,,0000,0000,0000,,or the Sharks, possibly. But we'll see. I\Ndon't Dialogue: 0,0:04:38.82,0:04:41.27,Default,,0000,0000,0000,,want to start a sports rivalry today. Dialogue: 0,0:04:41.27,0:04:45.83,Default,,0000,0000,0000,,So you know, this basically ranged from small\Nannoyances Dialogue: 0,0:04:45.83,0:04:49.71,Default,,0000,0000,0000,,to, you know, major issues with this API.\NSo Dialogue: 0,0:04:49.71,0:04:52.62,Default,,0000,0000,0000,,we'd have annoyances like this, where some\Nresponses would Dialogue: 0,0:04:52.62,0:04:55.37,Default,,0000,0000,0000,,come back with an id for the team, and Dialogue: 0,0:04:55.37,0:04:57.18,Default,,0000,0000,0000,,others would come back with a code. And in Dialogue: 0,0:04:57.18,0:04:59.55,Default,,0000,0000,0000,,this case, both of them refer to Anaheim.\NSo Dialogue: 0,0:04:59.55,0:05:01.49,Default,,0000,0000,0000,,this is a minor annoyance. You can code around Dialogue: 0,0:05:01.49,0:05:02.05,Default,,0000,0000,0000,,that. Dialogue: 0,0:05:02.05,0:05:06.14,Default,,0000,0000,0000,,Here, we have an undocumented bug, where basically\Nthe Dialogue: 0,0:05:06.14,0:05:07.87,Default,,0000,0000,0000,,goals were all supposed to be as a part Dialogue: 0,0:05:07.87,0:05:09.63,Default,,0000,0000,0000,,of an array, but if you only had one Dialogue: 0,0:05:09.63,0:05:11.86,Default,,0000,0000,0000,,goal, it would be an object. And sadly we Dialogue: 0,0:05:11.86,0:05:16.39,Default,,0000,0000,0000,,discovered this one in production, during\Na game. So Dialogue: 0,0:05:16.39,0:05:18.06,Default,,0000,0000,0000,,that wasn't ideal. Dialogue: 0,0:05:18.06,0:05:21.27,Default,,0000,0000,0000,,But, worst of all, after we had gone through Dialogue: 0,0:05:21.27,0:05:24.27,Default,,0000,0000,0000,,all of the trouble of fixing these, we realized Dialogue: 0,0:05:24.27,0:05:26.89,Default,,0000,0000,0000,,that there was no versioning on this API.\NSo, Dialogue: 0,0:05:26.89,0:05:30.25,Default,,0000,0000,0000,,even if we fixed it, we might be fixing Dialogue: 0,0:05:30.25,0:05:35.24,Default,,0000,0000,0000,,it again a week later. So this is basically Dialogue: 0,0:05:35.24,0:05:38.71,Default,,0000,0000,0000,,what it felt like to work with their API. Dialogue: 0,0:05:38.71,0:05:41.74,Default,,0000,0000,0000,,So, another project I worked on, this is just Dialogue: 0,0:05:41.74,0:05:44.39,Default,,0000,0000,0000,,kind of a fun side project, was a Snapchat Dialogue: 0,0:05:44.39,0:05:47.58,Default,,0000,0000,0000,,API Client, so I could, you know, work with Dialogue: 0,0:05:47.58,0:05:51.62,Default,,0000,0000,0000,,the Snapchat private API. And, well, one of\Nthese Dialogue: 0,0:05:51.62,0:05:55.81,Default,,0000,0000,0000,,examples is extreme, in that there is haphazard\Ndocumentation, Dialogue: 0,0:05:55.81,0:05:59.24,Default,,0000,0000,0000,,or no documentation, in this case. I think\Nwe've Dialogue: 0,0:05:59.24,0:06:03.92,Default,,0000,0000,0000,,all worked with APIs that have improper documentation. Dialogue: 0,0:06:03.92,0:06:05.25,Default,,0000,0000,0000,,But in this case we didn't even know what Dialogue: 0,0:06:05.25,0:06:07.24,Default,,0000,0000,0000,,the requests were, so we had to figure that Dialogue: 0,0:06:07.24,0:06:11.24,Default,,0000,0000,0000,,out. There's also bizarre obfuscation implanted\Ninside of the Dialogue: 0,0:06:11.24,0:06:15.70,Default,,0000,0000,0000,,app itself that basically encrypted, on their\NiPhone, so Dialogue: 0,0:06:15.70,0:06:19.01,Default,,0000,0000,0000,,people like me couldn't go in and build things Dialogue: 0,0:06:19.01,0:06:21.17,Default,,0000,0000,0000,,like this. And there's a GitHub link if you're Dialogue: 0,0:06:21.17,0:06:22.28,Default,,0000,0000,0000,,curious. Dialogue: 0,0:06:22.28,0:06:25.53,Default,,0000,0000,0000,,So, now that we've talked a little bit about Dialogue: 0,0:06:25.53,0:06:28.73,Default,,0000,0000,0000,,why it's important and outlined some of the\Nproblems Dialogue: 0,0:06:28.73,0:06:31.29,Default,,0000,0000,0000,,you might encounter, we're gonna talk about\Nhow you're Dialogue: 0,0:06:31.29,0:06:36.18,Default,,0000,0000,0000,,actually going to test these. Dialogue: 0,0:06:36.18,0:06:38.24,Default,,0000,0000,0000,,So first we need to ask ourselves, what is Dialogue: 0,0:06:38.24,0:06:43.10,Default,,0000,0000,0000,,different about services than regular code\Nthat we're testing? Dialogue: 0,0:06:43.10,0:06:47.15,Default,,0000,0000,0000,,Well, first of all, we have external network\Nrequests Dialogue: 0,0:06:47.15,0:06:49.80,Default,,0000,0000,0000,,that are being made, and second of all, you Dialogue: 0,0:06:49.80,0:06:51.86,Default,,0000,0000,0000,,don't own the code, so you can't really do Dialogue: 0,0:06:51.86,0:06:54.05,Default,,0000,0000,0000,,unit testing on it. It all has to be Dialogue: 0,0:06:54.05,0:06:56.93,Default,,0000,0000,0000,,done from integration test perspective. Dialogue: 0,0:06:56.93,0:07:01.93,Default,,0000,0000,0000,,So, what I propose for your tests, in general, Dialogue: 0,0:07:01.93,0:07:05.82,Default,,0000,0000,0000,,is that you turn Airplane Mode on. This, I Dialogue: 0,0:07:05.82,0:07:08.24,Default,,0000,0000,0000,,find, is the best way to think about your Dialogue: 0,0:07:08.24,0:07:11.51,Default,,0000,0000,0000,,tests, because, first of all, failure is really\Nbad Dialogue: 0,0:07:11.51,0:07:14.68,Default,,0000,0000,0000,,in testing, and you shouldn't be making any,\Nany Dialogue: 0,0:07:14.68,0:07:16.82,Default,,0000,0000,0000,,network requests. Dialogue: 0,0:07:16.82,0:07:18.77,Default,,0000,0000,0000,,So I think of this kind of in two Dialogue: 0,0:07:18.77,0:07:20.89,Default,,0000,0000,0000,,ways. First of all, so it's Airplane Mode\Nin Dialogue: 0,0:07:20.89,0:07:23.30,Default,,0000,0000,0000,,the test mode so you can't do these things. Dialogue: 0,0:07:23.30,0:07:24.96,Default,,0000,0000,0000,,But also it should be a test that you Dialogue: 0,0:07:24.96,0:07:28.36,Default,,0000,0000,0000,,can run on an airplane. Basically meaning\Nthat if Dialogue: 0,0:07:28.36,0:07:31.11,Default,,0000,0000,0000,,you're, you know, on a long trans-Atlantic\Nflight or Dialogue: 0,0:07:31.11,0:07:33.36,Default,,0000,0000,0000,,in the RailsConf lobby, you can still make\Nyour Dialogue: 0,0:07:33.36,0:07:39.60,Default,,0000,0000,0000,,tests and, and they won't fail because of\Nnetwork Dialogue: 0,0:07:39.60,0:07:42.18,Default,,0000,0000,0000,,issues. Dialogue: 0,0:07:42.18,0:07:44.93,Default,,0000,0000,0000,,So this means you should not interact with\Nyour Dialogue: 0,0:07:44.93,0:07:48.88,Default,,0000,0000,0000,,services from your testing environment. And\Nwe have a Dialogue: 0,0:07:48.88,0:07:52.83,Default,,0000,0000,0000,,few caveats which I'll get into now. So, this Dialogue: 0,0:07:52.83,0:07:56.77,Default,,0000,0000,0000,,includes dummy APIs. So there's some API makers\Nthat Dialogue: 0,0:07:56.77,0:07:59.29,Default,,0000,0000,0000,,have their real API, and then they have a Dialogue: 0,0:07:59.29,0:08:02.58,Default,,0000,0000,0000,,fake API which you can hit with requests,\Nbut Dialogue: 0,0:08:02.58,0:08:05.73,Default,,0000,0000,0000,,it doesn't make any changes to your data. Dialogue: 0,0:08:05.73,0:08:07.93,Default,,0000,0000,0000,,So you can't hit those, because those are\Nsomewhere Dialogue: 0,0:08:07.93,0:08:11.20,Default,,0000,0000,0000,,else on the network. But I do allow you Dialogue: 0,0:08:11.20,0:08:16.22,Default,,0000,0000,0000,,to make pre-recorded responses to those end\Npoints, and Dialogue: 0,0:08:16.22,0:08:18.13,Default,,0000,0000,0000,,that means you can record them within your\Ntest Dialogue: 0,0:08:18.13,0:08:19.92,Default,,0000,0000,0000,,suite, which we'll get into in a bit more Dialogue: 0,0:08:19.92,0:08:21.53,Default,,0000,0000,0000,,detail later. Dialogue: 0,0:08:21.53,0:08:25.30,Default,,0000,0000,0000,,So, for these examples, I'm going to be assuming Dialogue: 0,0:08:25.30,0:08:29.48,Default,,0000,0000,0000,,that you're using Rails, obviously, and that\Nyou're using Dialogue: 0,0:08:29.48,0:08:35.26,Default,,0000,0000,0000,,rspec for simplicities sake. So, it's time\Nto stub Dialogue: 0,0:08:35.26,0:08:36.92,Default,,0000,0000,0000,,out these requests. Dialogue: 0,0:08:36.92,0:08:40.81,Default,,0000,0000,0000,,So, when you're stubbing an object, you're\Nbasically - Dialogue: 0,0:08:40.81,0:08:43.04,Default,,0000,0000,0000,,for those who don't know - it's basically\Nputting Dialogue: 0,0:08:43.04,0:08:45.31,Default,,0000,0000,0000,,like a fake object in front of that object, Dialogue: 0,0:08:45.31,0:08:47.88,Default,,0000,0000,0000,,so you're hitting that object instead of hitting\Nthe Dialogue: 0,0:08:47.88,0:08:50.27,Default,,0000,0000,0000,,real one and, you know, saving time with,\Nlike Dialogue: 0,0:08:50.27,0:08:53.79,Default,,0000,0000,0000,,setup processes and stuff like that. And we're\Ndoing Dialogue: 0,0:08:53.79,0:08:56.37,Default,,0000,0000,0000,,a similar thing when you're stubbing a request\Nto Dialogue: 0,0:08:56.37,0:08:59.11,Default,,0000,0000,0000,,an endpoint, except we're saving a lot more\Ntime Dialogue: 0,0:08:59.11,0:09:00.87,Default,,0000,0000,0000,,when we're doing so, because we don't have\Nto Dialogue: 0,0:09:00.87,0:09:04.49,Default,,0000,0000,0000,,make that additional network request. Dialogue: 0,0:09:04.49,0:09:07.99,Default,,0000,0000,0000,,So there's some libraries that include built-in\Nstubbing. So Dialogue: 0,0:09:07.99,0:09:12.58,Default,,0000,0000,0000,,Typhoeus, if I pronounced that correctly,\NFaraday and Excon Dialogue: 0,0:09:12.58,0:09:17.68,Default,,0000,0000,0000,,are three examples of pretty widely-used HTTP\Nlibraries built Dialogue: 0,0:09:17.68,0:09:21.35,Default,,0000,0000,0000,,on top of net HTTP, I think, that have Dialogue: 0,0:09:21.35,0:09:24.09,Default,,0000,0000,0000,,built-in stubbing functionality. Dialogue: 0,0:09:24.09,0:09:26.69,Default,,0000,0000,0000,,But we can simplify this a little bit and Dialogue: 0,0:09:26.69,0:09:29.40,Default,,0000,0000,0000,,use something called webmock, which I'm sure\Nmany of Dialogue: 0,0:09:29.40,0:09:32.01,Default,,0000,0000,0000,,you have worked with in the past, which is Dialogue: 0,0:09:32.01,0:09:35.88,Default,,0000,0000,0000,,a general purpose stubbing library for your\Ntest suite, Dialogue: 0,0:09:35.88,0:09:39.87,Default,,0000,0000,0000,,so you don't have to learn each individual\Nlibrary's Dialogue: 0,0:09:39.87,0:09:42.75,Default,,0000,0000,0000,,stubbing methods. Dialogue: 0,0:09:42.75,0:09:44.60,Default,,0000,0000,0000,,So I'll take you through a quick example.\NHere Dialogue: 0,0:09:44.60,0:09:48.87,Default,,0000,0000,0000,,is basic spec_helper. Nothing really interesting\Nabout this, except Dialogue: 0,0:09:48.87,0:09:52.44,Default,,0000,0000,0000,,you have to include disable_net_connect! at\Nthe bottom. The Dialogue: 0,0:09:52.44,0:09:57.11,Default,,0000,0000,0000,,rest is boilerplate. So I've highlighted that.\NAnd, obviously, Dialogue: 0,0:09:57.11,0:09:58.88,Default,,0000,0000,0000,,with all of these examples, you should be\Nputting Dialogue: 0,0:09:58.88,0:10:02.18,Default,,0000,0000,0000,,the gem in your gem file and bundle installing Dialogue: 0,0:10:02.18,0:10:04.31,Default,,0000,0000,0000,,before you start. Dialogue: 0,0:10:04.31,0:10:06.93,Default,,0000,0000,0000,,So, when you put this in your code for Dialogue: 0,0:10:06.93,0:10:09.51,Default,,0000,0000,0000,,the first time, you'll get a really great\Nerror Dialogue: 0,0:10:09.51,0:10:11.62,Default,,0000,0000,0000,,with this, and I really like getting these\Nerrors, Dialogue: 0,0:10:11.62,0:10:14.37,Default,,0000,0000,0000,,because it tells me exactly, in my code, where Dialogue: 0,0:10:14.37,0:10:16.85,Default,,0000,0000,0000,,I'm making network requests. So if you're\Nnot already Dialogue: 0,0:10:16.85,0:10:22.29,Default,,0000,0000,0000,,doing airplane mode tests, you should just\Nplug this Dialogue: 0,0:10:22.29,0:10:25.62,Default,,0000,0000,0000,,disable_net_connect! in, and then you'll get\Nthis error, which Dialogue: 0,0:10:25.62,0:10:28.83,Default,,0000,0000,0000,,will tell you where you're making these network\Nrequests. Dialogue: 0,0:10:28.83,0:10:31.22,Default,,0000,0000,0000,,And it also is really handy, and it gives Dialogue: 0,0:10:31.22,0:10:33.81,Default,,0000,0000,0000,,you, actually, the request you're making at\Nthe bottom. Dialogue: 0,0:10:33.81,0:10:37.68,Default,,0000,0000,0000,,So you can copy and paste that into your Dialogue: 0,0:10:37.68,0:10:40.64,Default,,0000,0000,0000,,test in order to stub it automatically. And\Nobviously Dialogue: 0,0:10:40.64,0:10:42.88,Default,,0000,0000,0000,,you'll have to collect the body and the headers Dialogue: 0,0:10:42.88,0:10:47.08,Default,,0000,0000,0000,,yourself, if you need to use those as well. Dialogue: 0,0:10:47.08,0:10:51.57,Default,,0000,0000,0000,,So, for the following examples, we're gonna\Nuse probably Dialogue: 0,0:10:51.57,0:10:57.67,Default,,0000,0000,0000,,the most, sorry, most simple FacebookWrapper\Never invented. Basically, Dialogue: 0,0:10:57.67,0:11:01.49,Default,,0000,0000,0000,,all we're doing here is sending a GET request Dialogue: 0,0:11:01.49,0:11:06.27,Default,,0000,0000,0000,,to Facebook graph, the public API, for a user. Dialogue: 0,0:11:06.27,0:11:08.03,Default,,0000,0000,0000,,And what this does is it just returns, like, Dialogue: 0,0:11:08.03,0:11:11.26,Default,,0000,0000,0000,,very basic Facebook information about you.\NIt has your Dialogue: 0,0:11:11.26,0:11:15.05,Default,,0000,0000,0000,,Facebook username, your name, and an id and\Na Dialogue: 0,0:11:15.05,0:11:17.01,Default,,0000,0000,0000,,few other fields. Dialogue: 0,0:11:17.01,0:11:18.99,Default,,0000,0000,0000,,And then what we're doing with user_id up\Nat Dialogue: 0,0:11:18.99,0:11:22.74,Default,,0000,0000,0000,,the top is we are just pulling out the Dialogue: 0,0:11:22.74,0:11:26.98,Default,,0000,0000,0000,,value for key_id. So this, all it does is Dialogue: 0,0:11:26.98,0:11:33.06,Default,,0000,0000,0000,,return your Facebook id. Super, super simple.\NAnd make Dialogue: 0,0:11:33.06,0:11:34.96,Default,,0000,0000,0000,,sure, since we're putting it in lib, that\Nyou Dialogue: 0,0:11:34.96,0:11:38.28,Default,,0000,0000,0000,,require it at some point in your loading. Dialogue: 0,0:11:38.28,0:11:40.93,Default,,0000,0000,0000,,So now we're gonna look at a test for Dialogue: 0,0:11:40.93,0:11:43.13,Default,,0000,0000,0000,,this. So this is a test where we're not Dialogue: 0,0:11:43.13,0:11:45.44,Default,,0000,0000,0000,,making a network request, but we're stubbing\Nit out Dialogue: 0,0:11:45.44,0:11:49.31,Default,,0000,0000,0000,,with webmock. So, at the bottom, you can see Dialogue: 0,0:11:49.31,0:11:53.39,Default,,0000,0000,0000,,we're doing our testing case, and we're setting\Nup Dialogue: 0,0:11:53.39,0:11:57.77,Default,,0000,0000,0000,,an expectation that our user_id is equal to\NArjun's Dialogue: 0,0:11:57.77,0:12:00.89,Default,,0000,0000,0000,,user_id. And I'm using Arjun because he was\Nthe Dialogue: 0,0:12:00.89,0:12:03.56,Default,,0000,0000,0000,,maker of the Facebook graph API wrapper. Dialogue: 0,0:12:03.56,0:12:07.08,Default,,0000,0000,0000,,And, you can see, now, above, we are stubbing Dialogue: 0,0:12:07.08,0:12:10.13,Default,,0000,0000,0000,,the request, just like you'd stub an object.\NWe're Dialogue: 0,0:12:10.13,0:12:13.38,Default,,0000,0000,0000,,stubbing the method of the HTTP request and\Nthen Dialogue: 0,0:12:13.38,0:12:18.33,Default,,0000,0000,0000,,we're send, putting the link as the second\Nargument. Dialogue: 0,0:12:18.33,0:12:23.23,Default,,0000,0000,0000,,Next, we have to set up what it returns, Dialogue: 0,0:12:23.23,0:12:26.70,Default,,0000,0000,0000,,and this is just an HTTP response that we're Dialogue: 0,0:12:26.70,0:12:28.99,Default,,0000,0000,0000,,returning. So we want to put a status. Dialogue: 0,0:12:28.99,0:12:32.56,Default,,0000,0000,0000,,You can set headers, which I generally don't\Ndo, Dialogue: 0,0:12:32.56,0:12:35.42,Default,,0000,0000,0000,,but if you're doing any operations with the\Nheaders, Dialogue: 0,0:12:35.42,0:12:40.67,Default,,0000,0000,0000,,you should definitely set up these in your\Nresponses. Dialogue: 0,0:12:40.67,0:12:43.64,Default,,0000,0000,0000,,And the body, we have a really simple JSON Dialogue: 0,0:12:43.64,0:12:46.67,Default,,0000,0000,0000,,string. I've cut out a few fields for brevity. Dialogue: 0,0:12:46.67,0:12:49.17,Default,,0000,0000,0000,,But you can see it has an id, a Dialogue: 0,0:12:49.17,0:12:51.38,Default,,0000,0000,0000,,first_name, and a username. Dialogue: 0,0:12:51.38,0:12:54.65,Default,,0000,0000,0000,,So, this test will pass, and we're also making Dialogue: 0,0:12:54.65,0:12:58.20,Default,,0000,0000,0000,,no net requests, work requests. So, the reasons\Nit's Dialogue: 0,0:12:58.20,0:13:01.73,Default,,0000,0000,0000,,better is it, first of all, it's faster, and Dialogue: 0,0:13:01.73,0:13:04.02,Default,,0000,0000,0000,,we also aren't getting this intermittent failure\Nthat we Dialogue: 0,0:13:04.02,0:13:09.11,Default,,0000,0000,0000,,were talking about earlier from the network\Nrequest. Dialogue: 0,0:13:09.11,0:13:12.92,Default,,0000,0000,0000,,So, that's a good general way, but there's\Nways Dialogue: 0,0:13:12.92,0:13:15.20,Default,,0000,0000,0000,,we can also save time with this. So a Dialogue: 0,0:13:15.20,0:13:19.46,Default,,0000,0000,0000,,lot of the really popular libraries for API\Nwrappers Dialogue: 0,0:13:19.46,0:13:24.22,Default,,0000,0000,0000,,also include mock-services within themselves\Nor as an additional Dialogue: 0,0:13:24.22,0:13:26.86,Default,,0000,0000,0000,,library on the side, and they use that for, Dialogue: 0,0:13:26.86,0:13:29.65,Default,,0000,0000,0000,,you know, internal testing with their gems.\NSo I Dialogue: 0,0:13:29.65,0:13:32.45,Default,,0000,0000,0000,,recommend, if, if you can find one, to use Dialogue: 0,0:13:32.45,0:13:34.86,Default,,0000,0000,0000,,this before you can go and use webmock, because Dialogue: 0,0:13:34.86,0:13:36.04,Default,,0000,0000,0000,,it'll save you a lot of time. Dialogue: 0,0:13:36.04,0:13:38.81,Default,,0000,0000,0000,,And I'll take you through a quick example.\NSo Dialogue: 0,0:13:38.81,0:13:44.96,Default,,0000,0000,0000,,we're gonna use Facebook graph mock here.\NAnd all Dialogue: 0,0:13:44.96,0:13:48.37,Default,,0000,0000,0000,,we are doing is putting it into spec_helper.\NWe're Dialogue: 0,0:13:48.37,0:13:53.09,Default,,0000,0000,0000,,just including the methods and requiring it.\NPretty straightforward. Dialogue: 0,0:13:53.09,0:13:56.12,Default,,0000,0000,0000,,And now we're gonna look at a spec. Dialogue: 0,0:13:56.12,0:14:00.67,Default,,0000,0000,0000,,So, basically, all we're doing is we're wrapping\Nthe Dialogue: 0,0:14:00.67,0:14:05.19,Default,,0000,0000,0000,,test case within a wrapper that mocks out\Nthe Dialogue: 0,0:14:05.19,0:14:07.83,Default,,0000,0000,0000,,request. So basically, all this one's doing\Nis saying Dialogue: 0,0:14:07.83,0:14:11.45,Default,,0000,0000,0000,,we're sending a git request to Facebook graph\Nback Dialogue: 0,0:14:11.45,0:14:14.52,Default,,0000,0000,0000,,slash Arjun, and then the third argument,\Nin this Dialogue: 0,0:14:14.52,0:14:20.19,Default,,0000,0000,0000,,case, is users/arjun_public, which is where\Nthe JSON file Dialogue: 0,0:14:20.19,0:14:22.96,Default,,0000,0000,0000,,of this response is located in the gem. Dialogue: 0,0:14:22.96,0:14:26.91,Default,,0000,0000,0000,,So, you can also specify your own responses,\Nand Dialogue: 0,0:14:26.91,0:14:29.85,Default,,0000,0000,0000,,I'd recommend you do that, because I found,\Nactually, Dialogue: 0,0:14:29.85,0:14:34.41,Default,,0000,0000,0000,,some issues with the Facebook graph mock mocking,\Nlike, Dialogue: 0,0:14:34.41,0:14:38.67,Default,,0000,0000,0000,,responses, have some outdatedness in them. Dialogue: 0,0:14:38.67,0:14:41.96,Default,,0000,0000,0000,,So, but this, you know, example, I'm not gonna Dialogue: 0,0:14:41.96,0:14:43.61,Default,,0000,0000,0000,,take you through all of the gems that have Dialogue: 0,0:14:43.61,0:14:46.29,Default,,0000,0000,0000,,this. But this can go to show that there Dialogue: 0,0:14:46.29,0:14:49.73,Default,,0000,0000,0000,,are some benefits that you get from using\Nthis. Dialogue: 0,0:14:49.73,0:14:51.60,Default,,0000,0000,0000,,It's already stubbed for you. You don't have\Nto Dialogue: 0,0:14:51.60,0:14:55.71,Default,,0000,0000,0000,,learn the API endpoints in order to use it, Dialogue: 0,0:14:55.71,0:14:59.01,Default,,0000,0000,0000,,and some of these provide prerecorded responses\Nfor your Dialogue: 0,0:14:59.01,0:15:01.15,Default,,0000,0000,0000,,use, so you don't have to go out and Dialogue: 0,0:15:01.15,0:15:03.20,Default,,0000,0000,0000,,collect these. So it's just a good way of Dialogue: 0,0:15:03.20,0:15:06.85,Default,,0000,0000,0000,,saving time, if you're using some popular\Nlibraries. Dialogue: 0,0:15:06.85,0:15:10.78,Default,,0000,0000,0000,,Next, I'm going to take you through sham_rack,\Nwhich Dialogue: 0,0:15:10.78,0:15:14.00,Default,,0000,0000,0000,,is one of my more favorite ways of doing Dialogue: 0,0:15:14.00,0:15:15.87,Default,,0000,0000,0000,,this. I kind of find this to be a Dialogue: 0,0:15:15.87,0:15:20.49,Default,,0000,0000,0000,,fun way. Basically what sham_rock does, sorry,\Nsham_rack does Dialogue: 0,0:15:20.49,0:15:24.32,Default,,0000,0000,0000,,is it allows you to mount rack-based apps,\Nwhich Dialogue: 0,0:15:24.32,0:15:28.29,Default,,0000,0000,0000,,include Rails and Sinatra and others, and\Nit allows Dialogue: 0,0:15:28.29,0:15:33.52,Default,,0000,0000,0000,,you to make requests against these fake apps. Dialogue: 0,0:15:33.52,0:15:36.51,Default,,0000,0000,0000,,So, in this case, we're going to get a Dialogue: 0,0:15:36.51,0:15:39.77,Default,,0000,0000,0000,,little help from Sinatra in order to stub\Nout Dialogue: 0,0:15:39.77,0:15:45.55,Default,,0000,0000,0000,,these endpoints. So, spec_helper, the only\Nthing interesting is Dialogue: 0,0:15:45.55,0:15:50.36,Default,,0000,0000,0000,,that we leave in web-mock. Pretty boring there.\NBut Dialogue: 0,0:15:50.36,0:15:52.95,Default,,0000,0000,0000,,then we get to our fake. So I usually Dialogue: 0,0:15:52.95,0:15:56.65,Default,,0000,0000,0000,,just put this spec/support and then fake whatever\Nit Dialogue: 0,0:15:56.65,0:15:59.09,Default,,0000,0000,0000,,is, in this case fake_facebook. Dialogue: 0,0:15:59.09,0:16:01.37,Default,,0000,0000,0000,,And this just means it'll be loaded when you Dialogue: 0,0:16:01.37,0:16:05.80,Default,,0000,0000,0000,,run your specs automatically. But it won't\Nbe, obviously, Dialogue: 0,0:16:05.80,0:16:09.40,Default,,0000,0000,0000,,loaded into your production or staging environments,\Nor development. Dialogue: 0,0:16:09.40,0:16:12.00,Default,,0000,0000,0000,,So, in this case, at the top we can Dialogue: 0,0:16:12.00,0:16:15.11,Default,,0000,0000,0000,,see, we're calling sham_rack, and we're setting\Nup the Dialogue: 0,0:16:15.11,0:16:17.14,Default,,0000,0000,0000,,endpoint which we're hitting against, which\Nin this case Dialogue: 0,0:16:17.14,0:16:20.38,Default,,0000,0000,0000,,is graph dot facebook dot com. And 433 is Dialogue: 0,0:16:20.38,0:16:25.10,Default,,0000,0000,0000,,just specifying that we're using the HTTPS\NSSL link, Dialogue: 0,0:16:25.10,0:16:27.01,Default,,0000,0000,0000,,and dot Sinatra just means we're going to\Nbe Dialogue: 0,0:16:27.01,0:16:29.61,Default,,0000,0000,0000,,passing it in a Sinatra app. Dialogue: 0,0:16:29.61,0:16:33.83,Default,,0000,0000,0000,,So, basically, contained within this block\Nis a Sinatra Dialogue: 0,0:16:33.83,0:16:35.99,Default,,0000,0000,0000,,app, and you can do virtually anything you\Ncan Dialogue: 0,0:16:35.99,0:16:37.82,Default,,0000,0000,0000,,do with a regular Sinatra app, which is really Dialogue: 0,0:16:37.82,0:16:41.01,Default,,0000,0000,0000,,cool. So you can just, you're just basically\Nmounting Dialogue: 0,0:16:41.01,0:16:43.92,Default,,0000,0000,0000,,this and testing against it. Dialogue: 0,0:16:43.92,0:16:47.02,Default,,0000,0000,0000,,So, for those of you who don't use Sinatra Dialogue: 0,0:16:47.02,0:16:50.61,Default,,0000,0000,0000,,very much, all we're doing here is specifying\Nwith Dialogue: 0,0:16:50.61,0:16:53.63,Default,,0000,0000,0000,,the GET keyword that we're making a GET request Dialogue: 0,0:16:53.63,0:16:57.52,Default,,0000,0000,0000,,to back slash something, and just like Rails,\Nwhen Dialogue: 0,0:16:57.52,0:17:00.89,Default,,0000,0000,0000,,you rake routes you'll see the parametrization\Nof things Dialogue: 0,0:17:00.89,0:17:02.68,Default,,0000,0000,0000,,with a colon before it. We're doing the exact Dialogue: 0,0:17:02.68,0:17:04.96,Default,,0000,0000,0000,,same thing here with username. Dialogue: 0,0:17:04.96,0:17:07.90,Default,,0000,0000,0000,,So, you'll see, in the middle, in the link Dialogue: 0,0:17:07.90,0:17:10.74,Default,,0000,0000,0000,,we interpolate params username, and that's\Nhow you pull Dialogue: 0,0:17:10.74,0:17:14.17,Default,,0000,0000,0000,,that out. So this is essentially just returning\Na Dialogue: 0,0:17:14.17,0:17:17.92,Default,,0000,0000,0000,,string that is this response. You can obviously\Nspice Dialogue: 0,0:17:17.92,0:17:21.37,Default,,0000,0000,0000,,this up by setting status codes, adding conditionals\Nin Dialogue: 0,0:17:21.37,0:17:24.94,Default,,0000,0000,0000,,here if you need some more dynamic power,\Nand Dialogue: 0,0:17:24.94,0:17:28.58,Default,,0000,0000,0000,,also setting up the headers. And you can also, Dialogue: 0,0:17:28.58,0:17:31.33,Default,,0000,0000,0000,,which I sometimes do this in my testing, is Dialogue: 0,0:17:31.33,0:17:33.56,Default,,0000,0000,0000,,back it with like a small yml database, so Dialogue: 0,0:17:33.56,0:17:36.31,Default,,0000,0000,0000,,you can get some more realistic data than\Njust Dialogue: 0,0:17:36.31,0:17:39.51,Default,,0000,0000,0000,,a simple string. Dialogue: 0,0:17:39.51,0:17:46.47,Default,,0000,0000,0000,,So, that's the response. And. Now, when we're\Nwriting Dialogue: 0,0:17:46.47,0:17:52.17,Default,,0000,0000,0000,,our spec for sham_rack, all we're doing is\Nkeeping Dialogue: 0,0:17:52.17,0:17:53.78,Default,,0000,0000,0000,,it on this base level. We don't have to Dialogue: 0,0:17:53.78,0:17:56.74,Default,,0000,0000,0000,,wrap it with anything, because it will automatically,\Nin Dialogue: 0,0:17:56.74,0:17:59.70,Default,,0000,0000,0000,,your tests, pick up the fact that you have Dialogue: 0,0:17:59.70,0:18:02.71,Default,,0000,0000,0000,,sham_rack mounted, and it will automatically\Nhit against that Dialogue: 0,0:18:02.71,0:18:08.18,Default,,0000,0000,0000,,endpoint rather than hitting against the network. Dialogue: 0,0:18:08.18,0:18:12.76,Default,,0000,0000,0000,,So, you might ask, why is this better? I Dialogue: 0,0:18:12.76,0:18:14.88,Default,,0000,0000,0000,,think there are a few reasons. First, I find Dialogue: 0,0:18:14.88,0:18:18.10,Default,,0000,0000,0000,,it more dynamic. I find it more expressive\Nas Dialogue: 0,0:18:18.10,0:18:20.43,Default,,0000,0000,0000,,well, and you can really add, you know, as Dialogue: 0,0:18:20.43,0:18:24.18,Default,,0000,0000,0000,,much functionality you need to test your integrations\Nas Dialogue: 0,0:18:24.18,0:18:25.77,Default,,0000,0000,0000,,you want. And you can also back it with Dialogue: 0,0:18:25.77,0:18:28.97,Default,,0000,0000,0000,,yml if you need, you know, some pre-population\Nof, Dialogue: 0,0:18:28.97,0:18:32.53,Default,,0000,0000,0000,,you know, real data. And it's also more readable. Dialogue: 0,0:18:32.53,0:18:34.76,Default,,0000,0000,0000,,Let's go back to this for a second. And, Dialogue: 0,0:18:34.76,0:18:37.48,Default,,0000,0000,0000,,you can see, like, reading through this is\Na Dialogue: 0,0:18:37.48,0:18:39.34,Default,,0000,0000,0000,,lot easier to parse through, and you know\Nwhere Dialogue: 0,0:18:39.34,0:18:41.86,Default,,0000,0000,0000,,the API requests are being made to, versus\Nthe Dialogue: 0,0:18:41.86,0:18:44.83,Default,,0000,0000,0000,,stubbing we showed in the first example, with\Nweb-mock, Dialogue: 0,0:18:44.83,0:18:46.27,Default,,0000,0000,0000,,is a little bit hard to read. So that's Dialogue: 0,0:18:46.27,0:18:48.86,Default,,0000,0000,0000,,why I prefer to use this. Dialogue: 0,0:18:48.86,0:18:52.95,Default,,0000,0000,0000,,So next, we're going to talk about vcr, which Dialogue: 0,0:18:52.95,0:18:55.30,Default,,0000,0000,0000,,is a pretty widely-used gem. And this one\Nhas Dialogue: 0,0:18:55.30,0:18:58.38,Default,,0000,0000,0000,,some other benefits that I think are really\Nimportant Dialogue: 0,0:18:58.38,0:19:03.22,Default,,0000,0000,0000,,to use. Basically it prerecords your responses,\Nand we'll Dialogue: 0,0:19:03.22,0:19:05.32,Default,,0000,0000,0000,,take you through an example. Dialogue: 0,0:19:05.32,0:19:10.05,Default,,0000,0000,0000,,So, spec_helper. The only thing interesting\Nhere. We have Dialogue: 0,0:19:10.05,0:19:13.23,Default,,0000,0000,0000,,the vcr configuration block, and all we're\Ndoing is Dialogue: 0,0:19:13.23,0:19:18.52,Default,,0000,0000,0000,,setting a cassette library. So that's basically\Nwhere these Dialogue: 0,0:19:18.52,0:19:21.03,Default,,0000,0000,0000,,responses will be saved. And then we're hooking\Ninto Dialogue: 0,0:19:21.03,0:19:24.35,Default,,0000,0000,0000,,web-mock, because that's the stubbing library\Nwe're using. Dialogue: 0,0:19:24.35,0:19:29.91,Default,,0000,0000,0000,,So, here's a spec. And as you can see, Dialogue: 0,0:19:29.91,0:19:34.17,Default,,0000,0000,0000,,it's really, really similar to the Facebook\Ngraph mock. Dialogue: 0,0:19:34.17,0:19:36.50,Default,,0000,0000,0000,,So basically what this does is, you're wrapping\Nit Dialogue: 0,0:19:36.50,0:19:40.51,Default,,0000,0000,0000,,in a block with vcr. So vcr, what it Dialogue: 0,0:19:40.51,0:19:42.63,Default,,0000,0000,0000,,does, is it goes out to the network and Dialogue: 0,0:19:42.63,0:19:46.01,Default,,0000,0000,0000,,makes the request for you, in your testing\Nenvironment, Dialogue: 0,0:19:46.01,0:19:48.66,Default,,0000,0000,0000,,and it pulls that response back and saves\Nit, Dialogue: 0,0:19:48.66,0:19:52.93,Default,,0000,0000,0000,,in this case, at Facebook user_arjun. Dialogue: 0,0:19:52.93,0:19:54.37,Default,,0000,0000,0000,,And the nice thing about this is you don't Dialogue: 0,0:19:54.37,0:19:58.09,Default,,0000,0000,0000,,have to go out and collect your own responses, Dialogue: 0,0:19:58.09,0:19:59.67,Default,,0000,0000,0000,,which I find to be pretty tedious and also Dialogue: 0,0:19:59.67,0:20:03.24,Default,,0000,0000,0000,,error prone. But, it also means you don't\Nhave Dialogue: 0,0:20:03.24,0:20:08.50,Default,,0000,0000,0000,,to break airplane mode with your tests, because\Nyou Dialogue: 0,0:20:08.50,0:20:11.07,Default,,0000,0000,0000,,can run this before, and you can cache all Dialogue: 0,0:20:11.07,0:20:14.67,Default,,0000,0000,0000,,of the JSON responses and play them back in Dialogue: 0,0:20:14.67,0:20:17.56,Default,,0000,0000,0000,,your build. So when you're running it on Travis Dialogue: 0,0:20:17.56,0:20:20.01,Default,,0000,0000,0000,,EI or Circle or whatever you happen to use, Dialogue: 0,0:20:20.01,0:20:23.37,Default,,0000,0000,0000,,you're not gonna break your build because\Nof network Dialogue: 0,0:20:23.37,0:20:27.79,Default,,0000,0000,0000,,failure. You're going to be using these cached\Nresponses. Dialogue: 0,0:20:27.79,0:20:31.06,Default,,0000,0000,0000,,And that also just allows you to verify the Dialogue: 0,0:20:31.06,0:20:33.68,Default,,0000,0000,0000,,responses. So, like I mentioned, it's a little\Nerror Dialogue: 0,0:20:33.68,0:20:36.09,Default,,0000,0000,0000,,prone. I've tried collecting these responses\Non my own Dialogue: 0,0:20:36.09,0:20:39.06,Default,,0000,0000,0000,,and, you know, sometimes I copy and paste\Nthem Dialogue: 0,0:20:39.06,0:20:41.55,Default,,0000,0000,0000,,wrong and come up with an issue. So this Dialogue: 0,0:20:41.55,0:20:43.58,Default,,0000,0000,0000,,kind of allows you to, like, have a nice Dialogue: 0,0:20:43.58,0:20:46.93,Default,,0000,0000,0000,,programatic way of pulling those in. Dialogue: 0,0:20:46.93,0:20:51.11,Default,,0000,0000,0000,,So, there's also an additional build process\Nyou can Dialogue: 0,0:20:51.11,0:20:54.70,Default,,0000,0000,0000,,add. So, for the NHL example I talked about, Dialogue: 0,0:20:54.70,0:20:56.59,Default,,0000,0000,0000,,the problem was there was no versioning. So\Nwhat Dialogue: 0,0:20:56.59,0:21:00.03,Default,,0000,0000,0000,,you can do is, if you want bonus points, Dialogue: 0,0:21:00.03,0:21:03.08,Default,,0000,0000,0000,,and you are really dependent on an API that Dialogue: 0,0:21:03.08,0:21:05.15,Default,,0000,0000,0000,,doesn't have versioning, you can do some kind\Nof Dialogue: 0,0:21:05.15,0:21:08.62,Default,,0000,0000,0000,,build process or, you know, test setup, where\Nyou're Dialogue: 0,0:21:08.62,0:21:11.33,Default,,0000,0000,0000,,basically running it outside of your normal\Ntest mode, Dialogue: 0,0:21:11.33,0:21:13.97,Default,,0000,0000,0000,,and you check the casettes for diffs, and\Nverify Dialogue: 0,0:21:13.97,0:21:17.07,Default,,0000,0000,0000,,that the responses are not changed from before.\NSo Dialogue: 0,0:21:17.07,0:21:19.03,Default,,0000,0000,0000,,this can help you avoid versioning issues.\NSo I Dialogue: 0,0:21:19.03,0:21:23.71,Default,,0000,0000,0000,,recommend that if you're using something like\NNHL API. Dialogue: 0,0:21:23.71,0:21:26.94,Default,,0000,0000,0000,,So, the next one we're gonna briefly talk\Nabout Dialogue: 0,0:21:26.94,0:21:31.20,Default,,0000,0000,0000,,is puffing-billy. And, aside from having a\Nreally cool Dialogue: 0,0:21:31.20,0:21:34.99,Default,,0000,0000,0000,,name and a nice logo on their GitHub, this Dialogue: 0,0:21:34.99,0:21:37.96,Default,,0000,0000,0000,,is an interesting gem to use. We're not gonna Dialogue: 0,0:21:37.96,0:21:40.44,Default,,0000,0000,0000,,use an example here, but basically what it\Nis Dialogue: 0,0:21:40.44,0:21:44.59,Default,,0000,0000,0000,,is for in-browser requests. So basically if\Nyou're having Dialogue: 0,0:21:44.59,0:21:49.72,Default,,0000,0000,0000,,integrations that are browser-based, you can\Nrecord and reuse. Dialogue: 0,0:21:49.72,0:21:54.51,Default,,0000,0000,0000,,Just like vcr, and use those responses again. Dialogue: 0,0:21:54.51,0:21:58.64,Default,,0000,0000,0000,,So, I don't want you guys to think that Dialogue: 0,0:21:58.64,0:22:00.43,Default,,0000,0000,0000,,all of this has to be done in Ruby, Dialogue: 0,0:22:00.43,0:22:03.100,Default,,0000,0000,0000,,and that you have to use vcr to first Dialogue: 0,0:22:03.100,0:22:06.38,Default,,0000,0000,0000,,record your responses. There's a lot of tools\Nout Dialogue: 0,0:22:06.38,0:22:11.49,Default,,0000,0000,0000,,there that will help you to collect these\Nresponses, Dialogue: 0,0:22:11.49,0:22:13.94,Default,,0000,0000,0000,,test API endpoints faster, and I want to share Dialogue: 0,0:22:13.94,0:22:17.26,Default,,0000,0000,0000,,some of those with you. Dialogue: 0,0:22:17.26,0:22:21.51,Default,,0000,0000,0000,,So, Chrome Dev Tools. Has anyone heard of\Nthis Dialogue: 0,0:22:21.51,0:22:24.83,Default,,0000,0000,0000,,in here? Yeah. Probably, probably all of you.\NBut Dialogue: 0,0:22:24.83,0:22:26.25,Default,,0000,0000,0000,,this is the first one I'm mentioning because\NI Dialogue: 0,0:22:26.25,0:22:29.94,Default,,0000,0000,0000,,use it, probably every day. Obviously it gives\Nyou Dialogue: 0,0:22:29.94,0:22:33.40,Default,,0000,0000,0000,,a really nice way of viewing responses and\Nrequests Dialogue: 0,0:22:33.40,0:22:36.56,Default,,0000,0000,0000,,and resending them. So super useful. I'm not\Ngonna Dialogue: 0,0:22:36.56,0:22:38.26,Default,,0000,0000,0000,,get too far in-depth in that one because I'm Dialogue: 0,0:22:38.26,0:22:41.14,Default,,0000,0000,0000,,assuming most people have worked with it.\NBut it Dialogue: 0,0:22:41.14,0:22:42.35,Default,,0000,0000,0000,,doesn't hurt to mention. Dialogue: 0,0:22:42.35,0:22:45.59,Default,,0000,0000,0000,,So next, Postman. If you want to stay within Dialogue: 0,0:22:45.59,0:22:48.89,Default,,0000,0000,0000,,Chrome. This is an extension you can use.\NAnd Dialogue: 0,0:22:48.89,0:22:51.80,Default,,0000,0000,0000,,it basically gives you a user interface around\Nrunning Dialogue: 0,0:22:51.80,0:22:55.42,Default,,0000,0000,0000,,these requests so that you can have kind of Dialogue: 0,0:22:55.42,0:22:57.88,Default,,0000,0000,0000,,an easier way to play with re, requests and Dialogue: 0,0:22:57.88,0:23:00.18,Default,,0000,0000,0000,,responses. And it allows you save them. It\Ngives Dialogue: 0,0:23:00.18,0:23:04.73,Default,,0000,0000,0000,,you, you know, a time in milliseconds of completion. Dialogue: 0,0:23:04.73,0:23:07.54,Default,,0000,0000,0000,,And this one I think is, I was working Dialogue: 0,0:23:07.54,0:23:12.59,Default,,0000,0000,0000,,on a Tinder API Client for fun, so. That's Dialogue: 0,0:23:12.59,0:23:15.30,Default,,0000,0000,0000,,what these requests are for. So, that one's\Nactually Dialogue: 0,0:23:15.30,0:23:17.73,Default,,0000,0000,0000,,up on my GitHub, too, if you're curious. Dialogue: 0,0:23:17.73,0:23:20.42,Default,,0000,0000,0000,,So, I use that a lot. But if you Dialogue: 0,0:23:20.42,0:23:23.52,Default,,0000,0000,0000,,like to stay command line based, I would recommend Dialogue: 0,0:23:23.52,0:23:29.75,Default,,0000,0000,0000,,HTTPie. It's basically an easier-to-use version\Nof curl, and Dialogue: 0,0:23:29.75,0:23:31.97,Default,,0000,0000,0000,,it doesn't have, like, quite the archaic syntax\Ncurl Dialogue: 0,0:23:31.97,0:23:35.26,Default,,0000,0000,0000,,has. So, I think it's, you know, worthy. Worthy Dialogue: 0,0:23:35.26,0:23:37.52,Default,,0000,0000,0000,,of use. And, you know, it'd be easier, obviously, Dialogue: 0,0:23:37.52,0:23:39.74,Default,,0000,0000,0000,,you know, to run a script around this than Dialogue: 0,0:23:39.74,0:23:42.03,Default,,0000,0000,0000,,it would be to run it around Postman. So Dialogue: 0,0:23:42.03,0:23:44.36,Default,,0000,0000,0000,,if you need to do something more programatic,\Nthis Dialogue: 0,0:23:44.36,0:23:46.65,Default,,0000,0000,0000,,is probably your best option. Dialogue: 0,0:23:46.65,0:23:50.34,Default,,0000,0000,0000,,And, one last tool I really like to use Dialogue: 0,0:23:50.34,0:23:54.38,Default,,0000,0000,0000,,is called Charles. And Charles does a lot\Nof Dialogue: 0,0:23:54.38,0:23:57.29,Default,,0000,0000,0000,,the same things as Chrome Dev Tools does,\Nbut Dialogue: 0,0:23:57.29,0:24:00.86,Default,,0000,0000,0000,,it acts as a proxy. So it basically captures, Dialogue: 0,0:24:00.86,0:24:03.58,Default,,0000,0000,0000,,you know, requests between you and your network.\NSo Dialogue: 0,0:24:03.58,0:24:06.25,Default,,0000,0000,0000,,you can set this up to capture any request Dialogue: 0,0:24:06.25,0:24:11.09,Default,,0000,0000,0000,,from your Mac machine, or you can proxy in Dialogue: 0,0:24:11.09,0:24:13.97,Default,,0000,0000,0000,,your phone as well. So I found this really Dialogue: 0,0:24:13.97,0:24:17.26,Default,,0000,0000,0000,,valuable when I was testing out the request\Nfrom Dialogue: 0,0:24:17.26,0:24:20.75,Default,,0000,0000,0000,,the Snapchat client, because it allowed me\Nto see Dialogue: 0,0:24:20.75,0:24:22.100,Default,,0000,0000,0000,,what my phone was making for requests and\Nrecord Dialogue: 0,0:24:22.100,0:24:25.49,Default,,0000,0000,0000,,those. And especially when we didn't know\Nwhat the Dialogue: 0,0:24:25.49,0:24:28.57,Default,,0000,0000,0000,,request was, it was very helpful in that case. Dialogue: 0,0:24:28.57,0:24:31.69,Default,,0000,0000,0000,,And it's also cool because, you know, when\Nyou're Dialogue: 0,0:24:31.69,0:24:35.76,Default,,0000,0000,0000,,building an API on Ruby and you want to Dialogue: 0,0:24:35.76,0:24:37.97,Default,,0000,0000,0000,,build on iOS client with it, and you're not Dialogue: 0,0:24:37.97,0:24:40.13,Default,,0000,0000,0000,,really sure how often to pull and stuff, I Dialogue: 0,0:24:40.13,0:24:42.43,Default,,0000,0000,0000,,sometimes pull this up, and I'll just see\Nwhat Dialogue: 0,0:24:42.43,0:24:44.63,Default,,0000,0000,0000,,other apps are doing. So it's a good way Dialogue: 0,0:24:44.63,0:24:47.34,Default,,0000,0000,0000,,of debugging other peoples work and, you know,\Nseeing Dialogue: 0,0:24:47.34,0:24:51.23,Default,,0000,0000,0000,,how they're doing it well. So, I highly recommend Dialogue: 0,0:24:51.23,0:24:54.32,Default,,0000,0000,0000,,you check it out. It's pretty easy to use, Dialogue: 0,0:24:54.32,0:24:57.44,Default,,0000,0000,0000,,and you can use it with SSL requests as Dialogue: 0,0:24:57.44,0:24:57.98,Default,,0000,0000,0000,,well. Dialogue: 0,0:24:57.98,0:25:00.84,Default,,0000,0000,0000,,So, here's some additional reading. I know\Nyou won't Dialogue: 0,0:25:00.84,0:25:02.35,Default,,0000,0000,0000,,have time to write this all down. I'll post Dialogue: 0,0:25:02.35,0:25:07.83,Default,,0000,0000,0000,,the slides on my Twitter. But, next up, let's Dialogue: 0,0:25:07.83,0:25:09.72,Default,,0000,0000,0000,,bring it all together. Dialogue: 0,0:25:09.72,0:25:12.69,Default,,0000,0000,0000,,So, we went over the what, the why, and Dialogue: 0,0:25:12.69,0:25:16.45,Default,,0000,0000,0000,,the how of testing services. So, we've shown\Nthat Dialogue: 0,0:25:16.45,0:25:19.83,Default,,0000,0000,0000,,testing services is crucial. They make up\Nreally important Dialogue: 0,0:25:19.83,0:25:22.26,Default,,0000,0000,0000,,parts of your app, so skipping tests is pretty Dialogue: 0,0:25:22.26,0:25:25.42,Default,,0000,0000,0000,,dangerous. I'd have to say, if you're in doubt, Dialogue: 0,0:25:25.42,0:25:30.19,Default,,0000,0000,0000,,stub it out. Determine, when you're making\Nchoices between, Dialogue: 0,0:25:30.19,0:25:35.11,Default,,0000,0000,0000,,you know, web-mock, sham_rack, or puffing-billy,\Neven, you want Dialogue: 0,0:25:35.11,0:25:37.68,Default,,0000,0000,0000,,to determine the amount of flexibility the\Nneed and Dialogue: 0,0:25:37.68,0:25:40.19,Default,,0000,0000,0000,,the amount of extra work you're going to have. Dialogue: 0,0:25:40.19,0:25:42.99,Default,,0000,0000,0000,,For example, it probably takes more time to\Nmake Dialogue: 0,0:25:42.99,0:25:47.29,Default,,0000,0000,0000,,a sham_rack server and have dynamic responses\Nthan copying Dialogue: 0,0:25:47.29,0:25:52.59,Default,,0000,0000,0000,,and pasting the request you get from the web-mock Dialogue: 0,0:25:52.59,0:25:54.56,Default,,0000,0000,0000,,error. So, you kind of just need to look Dialogue: 0,0:25:54.56,0:25:57.47,Default,,0000,0000,0000,,at the project you have and determine what\Nuse Dialogue: 0,0:25:57.47,0:26:00.54,Default,,0000,0000,0000,,case best fits these options. Dialogue: 0,0:26:00.54,0:26:04.63,Default,,0000,0000,0000,,And, also, record responses to save time.\NI wish Dialogue: 0,0:26:04.63,0:26:06.59,Default,,0000,0000,0000,,I would have started doing this sooner. It's,\Nlike, Dialogue: 0,0:26:06.59,0:26:11.33,Default,,0000,0000,0000,,super useful. I would highly recommend you\Ndo that. Dialogue: 0,0:26:11.33,0:26:14.50,Default,,0000,0000,0000,,And next up, after me, I'd recommend you stick Dialogue: 0,0:26:14.50,0:26:17.42,Default,,0000,0000,0000,,around. I had the pleasure of pairing with\NAustin Dialogue: 0,0:26:17.42,0:26:20.84,Default,,0000,0000,0000,,yesterday, and I think his talk plays off\Nmy Dialogue: 0,0:26:20.84,0:26:23.76,Default,,0000,0000,0000,,talk a lot, in that it talks a lot Dialogue: 0,0:26:23.76,0:26:26.28,Default,,0000,0000,0000,,about inconsistent test failures. And he goes\Na lot Dialogue: 0,0:26:26.28,0:26:29.54,Default,,0000,0000,0000,,more in-depth on, you know, other kinds of\Ninconsistent Dialogue: 0,0:26:29.54,0:26:33.25,Default,,0000,0000,0000,,test failures. And you just should definitely\Nstick around Dialogue: 0,0:26:33.25,0:26:35.21,Default,,0000,0000,0000,,if you have the time. Dialogue: 0,0:26:35.21,0:26:37.97,Default,,0000,0000,0000,,So that's it for today. Thank you for taking Dialogue: 0,0:26:37.97,0:26:40.62,Default,,0000,0000,0000,,the time to listen to my talk. And if Dialogue: 0,0:26:40.62,0:26:42.52,Default,,0000,0000,0000,,I don't get to your question, feel free to Dialogue: 0,0:26:42.52,0:26:44.45,Default,,0000,0000,0000,,shoot me an email, or if you just want Dialogue: 0,0:26:44.45,0:26:46.30,Default,,0000,0000,0000,,to chat. And you can also find me on Dialogue: 0,0:26:46.30,0:26:47.44,Default,,0000,0000,0000,,Twitter. So thanks a lot guys.