 I'm a developer at ThoughtWorks based here in Singapore. The Singaporeans among you may be able to tell from my accent that I'm not really from here, but Singapore is my second home. A bit of a plug. I co-organized Rails Girls in Singapore and we have an event coming out tomorrow morning at 9.30. And we have a coach briefing at 9. So I'm hoping to see some of you there tomorrow. So today I'm going to talk about collaborating with contracts. And let's start with real-life collaboration. When two parties collaborate in real life, what do they do? I think there are two possibilities. One, they can just do it. And this can happen if the two parties trust each other already. But this depends on goodwill because the obligations of both parties are not explicitly stated anywhere. Or they can negotiate a contract and adhere to the contract. This can be tedious at the beginning, but once the contract is there, the both parties can refer to it and when one of them don't fulfill any obligation, the other party knows exactly what that is. So this is an example of a contract in real life. We have, let's say, a supermarket who wants to get some ice cream from some supplier. So the contract will specify obligations on both sides. In this case, for the consumer, that the consumer has to order a weekend advance and that it has to pay at the time of order. And on the provider side, it specifies that the provider has to deliver within three business days and that the product must not expire within two months. That's all I have about real life. Now, moving along to not real life. When I mentioned collaboration, I meant it in the context of services. Can I get a show of hands? Who has had to deal with services? Whether consuming it or providing it? Right, quite a few. So just to refresh our minds a little bit, what is a service? A service is a reusable software component in encapsulating a business function. And it can be exposed over HTTP, Q or any other transfer protocol. For every service, there can be, there's a single provider and one or many consumers. And as a developer, you may be responsible for all of this or some or just one piece. Then there's a term, service contracts or contracts when it comes to services. At the most basic level, this can contain just an expectation about request and response. So, and they are usually written from the point of view of the provider. So the request will be the request that the provider understands. And the response is the response that the provider sends back to all consumers regardless of what they actually need. Service contracts can also have other things, for example, performance characteristics. For example, that the provider has to return a response within 100 milliseconds under a certain kind of load. But for today, we will focus on request and response. Just to visualize this a bit better, in this person service example, the response part of the contract will specify these three fields, ID, name and age, regardless of what the consumers actually need. At my workplace ThoughtWorks, I've been involved in a Ruby project for over a year now, and one of the things I learned is contract test. I fiddle around quite a bit with it, and I hope to share some cases where it might be useful. So with that, let's go to the first one. Coming back to the person service example, let's say that the provider, again, returns three fields, ID, name and age. And there are two consumers. Consumer A only cares actually about two fields, ID and age. The fact that the provider returns another field name, it doesn't really care about that. And then there's another consumer, consumer B, that expects also two fields, but a different one, ID and name. And then let's assume that there is another consumer coming in, which expects first name and last name. Well, obviously now to please consumer C, the provider has to send over first name and last name. Let's suppose that the team in charge of the provider just updates, just removes the field name and replaces it with first name and last name. What will happen? Consumers A and B will break because actually consumer B will break because it is the only one that expects first name and last name. So that's not great. Of course, the provider team could have kept name and just introduced the two new fields on top of the existing ones. But suppose they really do have to remove name, will they at least know that the consumers A and B will break before the consumers themselves complain. They will not if the provider doesn't even know what the consumers A and B expect from it. But it will if the expectations are explicit and known to them. So that is what consumer different contracts aim to help with. Consumer different contracts make consumer expectations explicit. Unlike service contracts which are written from the provider side or with the provider in mind, consumer different contracts are written from the point of view of the consumer. So we will have one consumer different contract per consumer. In this case, contract A will specify that consumer A needs ID and H to be returned from the provider. Contract B will specify that consumer B needs ID and name and so on. So taken individually, the consumer different contract is not exhaustive. But if we sum all of them up, then the provider can find out what it needs to return to satisfy all of the consumers. So in this case, if we sum up contract A, B and C, we will find out that the provider has to return ID, H, name, first name and last name. Why is this useful? Like any tool, services are only useful when they are actually used. And so the consumer has to know how to deal with the response that the provider returns. Otherwise it's not really going to be used. And the second point is that consumer different contracts make consumer expectations explicit. So when something breaks, you can find out which particular consumer is affected, how and how to fix it. Going one step further, there is also consumer driven contract test. It's quite a mouthful. But basically they have like any other test, they have the goodness of consumer different contracts and more. They are executable. So we don't have to refer to some long document, just execute something. And they can be run as part of the build pipeline so we can get quick and frequent feedback. Also, we know how Word documents become stale, but this is a test. And so as long as we run them regularly, we are kind of forced to update it. And so it becomes a living documentation of source of the system. Here is an example of when it is useful. Let's assume that there is an expensive call or computation that the provider needs to do to provide the field friends. But none of the consumer different contract tests break when we remove that field. So that means that tells us that it is safe to remove. If not because of the consumer different contract test, it will be harder to detect this. So we have to let's say go through some 20-page document to find out that it's not used and then remove it. The other thing about consumer different contract test is that it plays well with TDD. And here's a workflow. Consumer C is the one that's new. So we write consumer different contract tests for consumer C. And at first it will fail. It will fail because consumer C at first will not even make the right request to the provider. So that's exactly what we need to do to make it pass. This is the normal red green effector cycle that we have with TDD. So after that we can effector. And that's what we have to do on the consumer side. And then we move over to the provider side and we have the same cycle, red green effector. It will be red at first because the provider when given the response that's specified in the contract will not return what is expected. And so to make it green, we have to make the provider return what that particular consumer expects. And then we effector. The last part that's really important is that we have to make sure that the other consumer different contract test for the other consumers still passes as well because we want to make sure that all the existing consumers still work. So that is the first use case and to tie this back up. This is all about making consumer expectations explicit to the provider. So moving forward to the second one. Whenever we have service provider and consumer communicating with each other to make unit tests more deterministic, we often test around the service boundary. So on the consumer side, we often have a provider stub, for example, using something like WebMock. So then on the unit test for the consumer side, it will use the provider stub and it will verify that the consumer possesses the stub response properly. Moving on to the provider side, the provider side will typically have some kind of request from some fake consumer and then the test will verify that the provider returns the right response given their request. Usually at the beginning, everything will be good but after a while, there could be a mismatch. For example, here the consumer expects address and the provider stub returns that but the provider side itself is not updated. And so the unit test and also the unit test for the provider doesn't even know that this is happening. So everything seems okay from the provider's point of view. The unit test for both sides will continue to pass but the application may actually blow up because of this mismatch. So how can contract test help? It can help by verifying both sides against the same contract, thereby making sure that there is no mismatch. So one way this could look is we write expectations from the consumer side. Again, this is putting some emphasis on the consumer side and from there we generate the contract and then we verify that the provider adheres to the same contract. To tie this back up, this case was all about making sure that the provider and the consumer do their job and not just think they do their job. Making sure that they can really communicate with each other. So moving on to case three. In my team, we have had to keep two systems in sync via services and one end is handled by our team and another is handled by a separate team. For some business functions, we are in charge of the providers and for some others we are in charge of the consumers. We were starting from scratch so at the beginning there was nothing. None of the services have been built and there was no schema, no interface. So we started with that. We started with deciding on the service contract, specifically the interface and the schema for the request and the response. But we didn't want that to just be a document that will go stale. So we wanted an executable contract or effectively contract test. With an executable contract or contract test, the consumer team can go off on their own and when they are ready they can just execute the contract test and make sure they adhere to it. And the same goes for the provider side. The provider team can go off on their own and when they are ready they can execute the contract test and if it passes that means they are done. So with that both teams can develop their site independently. They don't have to wait for each other. And this is particularly useful because we had a lot of services and so we don't have to think hey let's do this one first and then let's do this other one. So if those tests pass on both the consumer and the provider side, we know that both sides will be able to communicate. But of course after that we still have to do integration testing. So this case was all about enabling parallel development. With that I'll go on to introduce you to a gem that we have been using to write our contract test. It's called PACT and it is assigned to write consumer driven contract test. The PACT workflow goes like this and I'll have to gloss over some of the details. First we write tests for the consumer side and we specify the service that we are testing that will have to be configured beforehand. And then in the given when then style we specify given a person with too many friends for example, upon receiving requests for person details. So this is just some description. And then we specify the request specification. So this is what we expect the request to be like. The details will be things like HTTP method, the path, the query params, form params and header. This will later be used to verify that the consumer makes the right call and also this is the call that the provider must understand. And then we move on to specifying the response. Similarly there are things like HTTP status and headers and then there's the body. The other thing is that PACT runs a mock server when you run a test. And the mock server will return this exact response when given the request that matches the request that we specified just before. And then on the next step we call the method on the app, on the consumer side that makes the actual HTTP request and we verify that it processes the response from the provider or from the mock provider properly. So we run it and we will see it fail at first. Again because the consumer doesn't even make the right HTTP call right now. Probably not any HTTP call at all. So at this stage to make it pass we just need to make that HTTP call and process it. And we don't need to care whether the provider is doing the right thing or whether it has even been implemented because it will be tested separately. When we run the consumer side test it will generate a PACT or JSON representation of the contract containing all the service, all the request and response specifications. The PACT file will then need to be shared over to the provider. This can be done either on your own or using the tools that PACT has. PACT actually has a suite of tools. One of them is called PACT broker which also handles things like versioning. So then we go to the provider side and we have to verify that the provider follows the PACT or the contract. And we do that just by doing a rate PACT verify. This fires actual HTTP request to the provider and so it exercises the full stack of the provider from the controller, the serializer, the service, the model, the whole thing. So it is exactly the same way that your actual consumer will exercise that. So a bit more on PACT, it also comes with an out of process or standalone stop. So we saw earlier that you can run your unit test against this stop but with this out of process stop you can also run your actual consumer, let's say a single page application against this provider stop. And you know that whatever response you get from here will be the exact one that your actual provider will return. PACT also has something called provider states. So we saw this earlier, given a person with too many friends. This is actually a provider state and what it gives us is the ability to set up and tear down data for that particular provider state. So this data setup will be run on the provider side just before the request is processed by the provider. So in this case I'm just inserting 10,000 friends to the person. By default, PACT tries to match the actual response from the provider with the one that is specified in the PACT exactly. So type and value both. But it is also possible to just verify on type using something like this, using actually PACT something like. And also it is possible to specify a rejects pattern and match based on that pattern. To sum up, we went through some use cases. First being making consumer expectations explicit, making sure both the consumer and the provider do their job and enabling parallel development. And we also covered PACT. With this, of course, the devil is in the details, for example, and how to integrate it with your existing test and also how much to assert on the response because each code path on your consumer side may have different expectation. And your mileage may vary as well because let's say if there's only one consumer for your service, then making consumer expectations explicit is probably not going to help that much. It also depends on how much influence you have on the team in charge of the provider and consumer because you need to assert some kind of influence for them to actually do this because this has to be done on both sides. So these are not silver bullets, but I hope I've provoked some thoughts in your head to start considering and start thinking about contract tests when you see collaboration using services. And like other tests, add them in your build pipeline for the quick and frequent feedback. That's all I have for today. Thank you so much, Tanya. Do you guys have any questions for her? Yeah, okay. Hi there, my name's Zach. So at the company I kind of work for, we're using kind of Rails almost to build a big monolith to pretty quickly explore the kind of problem space that we're in. And very quickly, once we understand it, we're kind of thinking about carverway services and maybe using more exotic languages where we can kind of squeeze more out of the boxes. So one of the problems we have is as soon as we start doing that, we'll need to sort of define these contracts, but we'll need to do it in kind of a more language agnostic way that's not necessarily bonded to Ruby or Rails or anything like that. Are there any sort of more general solutions that aren't so, like PACT is pretty glued to Ruby, but I mean, ideally we'd want something where we can kind of define a JSON specification that would work on whatever situation we'd want. So I'm kind of curious about that. Okay, so PACT actually, as I mentioned, it has a suite of tools, not just this gem and not just PACT broker, it also has an equivalent to rate PACT verify, but for providers they are not written in Ruby. So there are tools around PACT that are specifically for this. But having said that, there is another tool which I haven't used, it's called PACTO, it's very similar, it's just with an O at the end. And that one also supports non-Ruby service consumers and providers, so those two things are the ones that you can check out. All right, if you do, you can find Tanya during the break. Let's thank her again for coming up. Thank you.