Thursday, May 19, 2016

Parameterising contracts for interaction driven development



This is a follow on post about Contract, if you've not read any of the previous posts, this should serve as a good introduction. 

Having to specify single contract per file is a little painful, especially if you have a few scenarios to be tested. Lets look at a simple example, imagine I want a contract to verify that an endpoint exists and the correct status code will be returned. 





 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
{
  "info" : {
    "details": "The server should return the correct status for an endpoint"
  },
  "request" : {
    "method" : "GET",
    "path" : "/service/car"
  },
  "response" : {
    "status" : 200
  }
}

If we wanted to expand on this to include multiple endpoints, we would need to duplicate a lot of configuration. With parameters, we can reuse the same contract multiple times.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
  "info" : {
    "details": "The server should return the correct status for an endpoint"
  },
  "parameters" : [
    {
      "endpointName" : "car",
      "expectedStatus": 200
    },
    {
      "endpointName" : "jeep",
      "expectedStatus": 200
    },
    {
      "endpointName" : "bicycle",
      "expectedStatus": 404
    },
    {
      "endpointName" : "pedestrian",
      "expectedStatus": 404
    }
  ],
  "request" : {
    "method" : "GET",
    "path" : "/service/${contract.parameters.endpointName}"
  },
  "response" : {
    "status" : "${contract.parameters.expectedStatus}"
  }
}


A client, fed this contract will execute 4 requests, one for each parameter group. A server, fed this contract, will expand it into 4 contracts.

Links:

Tuesday, May 10, 2016

Contract 0.0.4, delivering expressions

This week saw the release of Contract 0.0.4 and the first months stats from maven central. About 30 unique downloads, I'm chuffed if even half of those people who downloaded it actually used it. Ok, on to what we did this week.

Wildcard expressions:

Having to hard code absolutely everything is never going to be very good for testing systems. People don't want to have to fill out contracts in that level of detail. There are also times when people cant predict what will be returned when a request is made to a server. With that in mind, we added the wildcard expression functionality.

We'd dipped our toes into this functionality 2 releases ago with the ${contract.timestamp} in a limited amount. We've expanded on that in our 0.0.4 release to include strings and numbers. We've limited its use to within string fields within JSON bodies for now.

These wildcards can be used to replace parts of the path, query parameters, headers and body. Looking at an example, lets use an online streaming service, and an API endpoint that is used to register new content. Lets write the contract for creating a new TV show.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "request" : {
    "method" : "POST",
    "path" : "/webmovies/library/tvshow",
    "body" : {
     "name" : "Imprisioned Construction",
     "year" : "2005",
     "productionCompany" : "BOX"
    }
  },
  "response" : {
    "status" : 201,
    "body" : {
     "id" : "${contract.anyNumber}",
     "name" : "Imprisioned Construction",
     "year" : "2005",
     "productionCompany" : "BOX",
     "addedOn" : "${contract.timestamp}"
    }
  }
}

This contact specifies that when a POST request is made to the 'webmovies/library/tvshow' url with the body specified. Then the server will respond with the CREATED response code, the same body as was in the request enriched with id and addedOn fields.

We can create a contract for reading a TV show from the service where we know effectively nothing and the test server will fill in the blanks.



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
{
  "request" : {
    "method" : "GET",
    "path" : "/webmovies/library/tvshow/${contract.anyString}"
  },
  "response" : {
    "status" : 200,
    "body" : {
     "id" : "${contract.anyNumber}",
     "name" : "${contract.anyString}",
     "year" : "${contract.anyNumber}",
     "productionCompany" : "${contract.anyString}",
     "addedOn" : "${contract.timestamp}"
    }
  }
}

Here any request valid request sent to the server will be given a valid response. 


Want to give it a try? Download our fat runnable jar from here and run it with :

1
java -jar contract-all-0.0.4.jar -s -p 9005 -g https://github.com/harmingcola/webmoviesContracts

Make a GET request to http://localhost:9005/__configure and the contracts loaded into that server will be listed.

Links:
Contract source
Contract docs
Webmovies contracts

Monday, May 2, 2016

Taking contract for a field test with Jenkins and Dashing

I've been working on Contract for a while now, and I'm starting to get that feeling that things are going a little too well on the build front ...... I want to take the project for a field test and see what happens.

The plan
I've been wanting to build a Dashing dashboard for my contract Jenkins builds. And instead of using and out of the box dashboard, I'd develop one myself. So, here our build pipeline :


Our code needs to pass through 5 stages before we're happy with it. However, to alert us to a problem, we want our dashboard to be red for any failure per project.

The Requirements
  • I want a Dashing dashboard for my Jenkins builds.
  • I want to display one tile per group of jobs.
    • Groups should be defined in the dashboard config.
    • If any job in the group is red, the group is red.
    • If all are green, the group is green.

The rules
  • Once i've the contract set, I cant go back to Jenkins. I can only develop the dashboard against the ContractServer. 

The Implementation

Before I can start with the dashboard I need to write my contracts. I have no idea what Jenkins payloads look like or what URLS to get them on. After having a look around I've decided to go with this endpoint /job/contract_build/lastBuild/api/json where 'contract_build' is the name of the job. 



Contracts have been written, one for each of my 5 build jobs for Contract, and another one to prove that the failure case works too. Because my builds are absolutely never never ever red.


Dashing projects aren't maven based, As part of Contract 0.0.3, well be releasing a fat runnable jar for running servers from the command line. Running the jar looks like :



I'm off to develop the dashboard, wish me luck ..... My ability to misspell 'Contract' as 'Contact' knows no bounds. Dashboard didn't take long to write. I know neither ruby nor coffeescript, so I've got that going for me. With the dashboard completed, I've got something that looks like the image below. This is exactly what we expect, all jobs in the contract group are green, and the 'interceptor_build' job in the interceptor group is failing.


Lets plug the dashboard into our real Jenkins and see what clicks.


Perfect!! Our contract group stays green because all the jobs are actually green. The interceptor group turns orange because it doesn't exist on our real Jenkins server. I think this can definitely be marked as a successful field test.

Contract docs are here and contract source is here.
Contract 0.0.3 has just been released to maven central. The stars of this release are certainly the maven plugins and fat jar. And by stars, I mean the only thing in the release