Friday, September 21, 2018

Outside-In TDD for the functional python server with Flask and SqlAlchemy




In the following video, you will see a graph and how in time we expand the code using the Outside-in TDD 

Requirements


We have an web API where we should be able to write and read articles and their comments.

Acceptance Test

We save an article:

POST /api/1/save/Article
{
"title":"New article",
"content":"The content"
}
and we receive the article + id
{
id: 13, - can be any value
title:"New article",
content:"The content"
}
We then add 2 new comments:
POST /api/1/save/Article
{
id: 13, - can be any value
comments:[
    {"comment":"This was awesome!"},
    {"comment":"I loved it as well!"},
]
}
response:
{
id: 13, - can be any value
title:"New article",
content:"The content"
}
and now reading the articles and the comments:
POST api/1/query/Article
{
    find: [id,title,content,{comments:[id,comment]}],
    where:{id:13}
}
should return
{"13":{

    id: 13, - can be any value
    comments:{
    "113":{"comment":"This was awesome!"},
    "114":{"comment":"I loved it as well!"},
    }
   }
   }

Outside-In TDD approach


Unlike classicist TDD, in Outside-In, you start the code from the outside, designing it along the way. You start with an acceptance test, then with the unit/integration tests and code needed until you make the acceptance test work:




So let's begin:

Step 1: Acceptance test






When we run it:




2. Step 2 moving in, 


From the outside, writing the first test for the service that will handle the url. A little bit of design, while writing the test: we consider, that we will use a function that will get the object from the database if we have an id in the json or will give us a brand new Article object if we have no id in the json.













Now if we properly do the code, the test will pass:








Step 3: moving furher in, database_services and get_database_object


However, we did not implement the get_database_object, which will work with the database. So for that we'll write the tests first:


or:



and






Now let's write the code to make it pass:







We write in fact 2 tests to cover both scenarios:  when editing or when adding a new article.


Step 4: now we move back and extend the api


We design it to read the data from json and transfer it to the database object. For that we'll use a function transfer_from_json





Once it passes, we move further:

Step 5: writing the transfer service













Now we make the test pass:





Step 6: back to extending the api

We now need to save the object with the data from the json into the db



For this, we extend the test:



and make it pass, then we move back to implementing using TDD the save_database_object

Step 7 extending the database_service to also save



Once we write the test, the code and make it pass:



we move back to the api

Step 7 extend the api





Step 8: TDD the extension:



Until we make it pass:




After a few more intermediary steps:

...

We will TDD all the necessary code to make the acceptance test pass: