A test-driven approach to developer communication

In teams that are distributed or partially distributed, there often is a need for a centralized online meeting point where everyone can discuss and share information about what they’re working on. Stuff like WhatsApp groups, Trello boards, github issue discussions and the classic mailing lists are some of the tools already in place for this.

For a team that I was working with which comprised mostly of students working on a mock project I needed a way to make sure that everyone was always on the same page and there was some written record of what the teams needed from each other, so that the teams didn’t have to come in and talk to each other all the time.

We were developing an application using the ASP.NET MVC Platform and we had a frontend team and a backend team working in tandem. We needed a way to make sure the frontend team communicated very clearly what data (in the form of Models, URLs, etc.) they needed from the backend team.

We had a design document and UI diagrams and ER diagrams and all of that already built, however the precise details of what exact object would be returned to the Views couldn’t be easily documented. For example, say for the Books list page, they need a Book Object that may look like this:

class Book
public virtual Item ItemId { get; set; } // Foreign Key
public int BookId { get; set; } // primary key
public string Title { get; set; }
public string Author { get; set; }
public DateTime DateOfPublishing { get; set; }

There were also common business logic rules that the frontend and the backend teams had to ensure, say, the ItemID, which was a foreign key could not be null.

Of course there’s a lot of ways to communicate this, I had a crazy idea. Rather than only have documents and diagrams that everyone has to be told about and explained and are difficult to maintain, we also right tests. The frontend team writes a test for the Book object that it needs from the controller and the backend team delivers that object, thus making the tests pass.

This way, the test would be the common format of communication, that teams use to officially tell each other what they need. The tests wouldn’t replace the documentation that already existed, but rather augment it.

So the scenario would go like this: The frontend team needs a list, specifically C#’s IEnumerable of Books, whose ItemID’s are not null. They write a test that looks like the following psuedocode:

public void BookListTest
// code to set up test

books = controller.List();
Assert.IsType(IEnumerable, books);
Assert.IsNotNull(books.Any(b => b.ItemId));
Assert.IsNotNull(books.Any(b => b.DateOfPublishing));

The test above says simply that the List() method, i.e. the List View of the controller returns a) An IEnumberable of Book objects, b) the ItemId for any book is not null and c) the DateOfPublishing for any book is not null.

Of course most of these rules would already be documented in the business logic, the tests just makes sure that when their built, that stuff is taken care of.

Both the frontend people and the backend people look at this test and go, “That’s what I’m getting, that’s what I need to do”. This is included in the code and this is a test. When it is first written, the test fails. Eventually it passes and everyone moves on to the next controller or what have you.

The idea came really from studying about how computer systems that aren’t made with the same architecture communicate. For example, consider how objects are serialized and sent over to other application servers in Java. They’re converted to a specific format that every system knows and then sent over to the other instance.

Consider this a way of serializing requirements. They’re codified and cemented in the form of tests so everyone is always aware of them. If there’s a flaw in the tests, they should be updated and that change is added into the code.

This approach, of course, has flaws. The biggest flaw that we found in our project was that the tests were often wrong, so they had to be updated to pass. However, this gave everyone who read the test a clearer understanding of what the component did.

In fact, you wouldn’t be completely wrong to think that this is pointless. Projects already have sequence diagrams and use cases and other detailed documentation that already solve this problem. This approach requires you to write a lot of tests, since this is technically a form of Test-Driven Development.

However, the primary benefit of this approach, is that now you have tests. It is correct that you need additional development time to write and debug tests. It is also correct that projects can get by without this approach because diagrams and documents, while not flawless work just fine. They can be a pain sometimes and this approach doesn’t solve all the problems of asynchronous development and distributed teams. However, with this approach, now you have tests!

In no way am I suggesting that this replace whatever already is available to any team in the world. However, writing tests can simply be a way to tell everyone on the team, exactly what needs to be done. This approach is meant to more augment existing documentation rather than replace it.

To verify the absolute effectiveness of this approach, there needs to be a proper study looking at data over a significant period of time. I hope you’ve found this article interesting and I believe this idea is worth looking into. I’m currently writing a paper about this approach and hopefully it all works out.