Designing with expectations, not implementations
If you heard about test driven development (TDD) and wanted to get started somewhere then this is for you. This post represents a summary of the experience I got through implementing TDD as part of our development process at Shaadi.
2 Things to ask yourself before going through this test process
When should I write tests?(Before vs After)
After: This is like getting an architect to create design after a building is built. People say developers are not good testers because we test the app as how we have implemented it. when we have already have implemented something and know that it works, it narrows down your thinking based on implementation you have done and we Write tests which shows our implementation works not if the expectations works. We even Hacks to make test pass, mess code and extra effort.
You will know whether what you built broke, but not what you missed in the first place.
Before: you are free to think about the task at hand, what are the expectations from the system, without having any constraints of your implementation, so you are free to think as a user, as a tester and then as a developer. And you clearly know beforehand where you are headed
Do my tests run fast?
Obviously you won’t write tests if it takes as much time as running it on device and as it takes to verify them manually. Tests should run as fast as possible and that’s why we are focusing on just plain Junit testing rather than integration tests here.
“But dude, the unit tests doesn’t cover the whole system and how will I know if my API doesn’t work”
First of all, APIs and backend request response structure are already thought of before implementing client side, so you’ll either have Swagger/Raml/Postman already to make a mock factory with JSON from them or if you don’t have then also during TDD when you’ll think of the data of request you will send and the type of response you expect to make your feature work, you can send this data factories you made to the server team to make APIs. A win-win situation.
“But how will I know that my View/UI will be as I am expecting”
Well you have to really keeps things simple enough that all the required data that is shown in UI comes from your viewmodel/presenter and view just takes that data and shows it without manipulating or adding some logic to it.
This mocking of view and data let’s you test everything as JUnit tests which are 10000x times faster than instrumentation test and will save u alot of time and give quick results even in a test suite of million test cases.
So when you are given a task, we think about contracts, Architecture and get down implementation it, but what do users and product want? They don’t care about code, they care about their expectations, so why shouldn’t we think alike, and start our feature with writing down expectations and implementing around it.
But even after listing down out expectations we need some way to verify that our expectation is working or completed as we expected so for that we the best way is to write tests. So that when we click that green button we know whether we achieved what we wanted or not. and when we do change something, there is something to tell whether you messed up or not.
This is Test driven development. Letting your expectations become test cases and let that tests lead your development process. And the reason why you should use it.
And they give you greatest and foremost quality of any product i.e it should work as expected. Tests maintain that.
And your QA will cry to test regression again and again but your machine won’t.
Here you ask what this feature should be doing?
In return you get
- Expectations of the feature
- Clarity about building
- Documention of features
You define the flow of the feature, how it starts, what message it passes to other objects and when it ends.
In return you get
- Relationship between objects.
- Flow of the feature.
- Mocks you will need.
- Knowing when it’s done.
Note: Until this process, you won’t be creating any classes or interfaces. When you reach here then you will start creating all the interface and classes with the methods you came to know in above 2 steps.
You will give life to the feature by creating them and now filling the implementation details of the flow to make it work. You will implement, run the test, check the result and repeat this till your test turn green.
After you are done with making the test pass and are done with it,
You leave the test and move on to another test, never wanting to see that test again.
You don’t have to bother testing the feature again or looking back as it’s in the test suite and your tests can run regression by themselves and give you output what broke during modification or updates to your application.
For code samples checkout this slidedeck: TDD — Designing with expectations not implementations