Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Contract Driven Development

Contract Driven Development

Have you ever used a web-based API that was poorly designed and inconsistent? Have you found gaps between the documentation and implementation? At Patientco, we have successfully implemented a Contract Driven Design methodology for APIs. Swagger is used to design RESTful endpoints before a line of code is written and the specification, documentation, and code are kept in sync through automated testing and deployment.

Avatar for Chris Church

Chris Church

October 21, 2016

Other Decks in Programming

Transcript

  1. Me • Chris Church • Full Stack Polyglot Developer •

    Minecraft Sysadmin for my 3 kids • Home-brewer, Competitive Shooter, and Amateur Carpenter
  2. Where I Work • SaaS Healthcare Payments Company • INC.

    500 Listed Company • LAMP-ish • Director of System Engineering and Architecture • We’re hiring!
  3. Talk Today • Overview of Contract Driven Development Approach •

    How we do CDD using Swagger and PHP • Goal: Make Better APIs
  4. Why Better APIs? • Maintainability • Flexibility • Encapsulation •

    Reuse • We can’t make great software without great APIs
  5. Swagger • Declarative specification for REST APIs • JSON or

    YAML • Large ecosystem of tools • Great for defining contracts!
  6. Swagger Assertions • github.com/Maks3w/SwaggerAssertions • How do you test that

    your API matches a Swagger spec? • Automatically validate the spec on every controller test
  7. Example Test public function testGetDisbursedPayments() {
 //...
 $response = $this->get("api/v1/payments");


    $this->assertEquals(200, $response->code);
 
 $jsonContent = json_decode($response->content);
 $this->assertEquals($payment->id, $jsonContent);
 }

  8. Example Test public function testGetDisbursedPayments() {
 //...
 $response = $this->get("api/v1/payments");


    $this->assertEquals(200, $response->code);
 
 $jsonContent = json_decode($response->content);
 $this->assertEquals($payment->id, $jsonContent);
 } 
 public function get($path, $input=array(), $validation=true) {
 return $this->request("GET", $path, $input, $validation);
 } public function request($method, $path, $post=array(), $validation=true) {
 //$request = ... $response = self::$app->process($request);
 
 if($validation) {
 self::validateRequest($method, $request->path, $post,
 json_decode($response->content),$response->code);
 }
 
 return $response;
 }
  9. Example Test private function validateRequest($method, $path, $post, $response, $responseCode) {


    $swaggerSpecFile = self::$swaggerPath . self::$app->name . "-spec.json";
 
 if (file_exists($swaggerSpecFile)) {
 $swaggerAssert = new AssertsTrait();
 $schemaManager = new SchemaManager('file://'. $swaggerSpecFile);
 
 if ($schemaManager) {
 try {
 $swaggerAssert->assertRequestBodyMatch($post, $schemaManager, '/' . $path, $method, 200);
 }
 catch (Exception $e) {
 self::fail($e->__toString());
 }
 
 try {
 $swaggerAssert->assertResponseBodyMatch($response, $schemaManager, '/' . $path, $method, $responseCode);
 }
 catch (Exception $e) {
 self::fail($e->__toString());
 }
 }
 else {
 self::fail("Failed to load Swagger Schema Manager from " . $swaggerSpecFile);
 }
 }
 else {
 self::fail("Unable to load Swagger definition at ". $swaggerSpecFile);
 }
 }
  10. More Swagger Assertions • Test Authentication • Versioning • Depends

    on versioning scheme • Contract coverage - like code coverage
  11. What is CDD? • Contract Driven Development • TL;DS: Build

    APIs and API-centric applications by defining a contract first and developing code around mocks and schema validations
  12. What is CDD? • TDD, BDD, DDD, ADD, YADD •

    Not really about contracts • The first steps determine the structure of the rest of the application.
  13. Methodology 1. Define a rough API specification 2. Define use

    cases against API 3. Define error cases 4. Begin coding 5. Iterate coding and API changes
  14. 1) Draft • High level pass over endpoints • Nouns

    • CRUD • Define Authentication • “Happy Path” responses
  15. 2) Use Cases • API User Stories • Typically multi-call

    flows • Find • Missing endpoints • Missing data • Inefficient access patterns
  16. 2) Use Cases Example 1. Request payment • POST /token

    2. Check payment status • GET /payments/{referenceid}
  17. 3) Error Cases • Decide on a standard convention for

    errors • HTTP Codes, Error Codes, Error Messages • Goal • Easy to understand • Easy to program against
  18. 3) Error Cases • Identify internal and external causes •

    Invalid Inputs • Unknown Values • Invalid Access • Internal Errors • Put these into your API Spec
  19. 4) Coding • Implement contract verification using Swagger assertions •

    Write tests calling (or simulating calls) to a controller, verifying response values, and using contract verification • Write controller logic until the test passes
  20. 5) Iterate • Make changes to the contract and regenerate

    mocks • Decide if your organization needs to version these changes • Some contract changes will break tests • Change controller behavior until the tests pass
  21. Post-Launch • Versioning your specification • Depends on how you

    version the API • Update API doc on deploy • Maintain schema validations on all unit and integration tests
  22. Wrapping Up • There are lots of tools for APIs

    - leverage them • Design your APIs like a user interface • Think through interactions and expectations • Keep your tests, code, and documentation in sync with automation