We are building an application using a completely test-driven approach. As developers, we are very familiar with unit tests but haven't been exposed to integrated / functional / acceptance tests. Hence this post.
The application exposes a web UI (HTML resources), which invokes a secured REST API (with JSON serialization), which then delegates to a core domain model (transactional application services and business entities) independent of any delivery mechanism. The REST API is to be made public eventually. Persistence is achieved using a relational database and an ORM. A standard Java / Spring / Hibernate technology stack is used.
If we wanted to do pure TDD, we would be writing the following tests:
- Selenium / WebDriver tests for the web UI
- integration tests for the REST API
- integration tests for the application service
- integration tests for the repository (persistence)
- unit tests for the web controllers (REST API)
- unit tests for the application service
- unit tests for the validator
By integration tests, I mean tests that target a fully functional application deployed on a production-like environment. By unit tests, I mean tests that target individual classes for which collaborators / dependencies have been replaced by test doubles (mocks, stubs, whatever).
Clearly, every test has a different perspective (user-centric for web tests, API consumer-centric for API tests, developer-centric for others) and validates different assertions (HTML element contents for web tests, HTTP responses and status codes for API tests, database contents and exceptions for application tests, edge cases for unit tests, etc.). But there's also a lot of overlap between all these tests, particularly when it comes to fixtures (e.g. user cannot register if other user with same email is already registered). As such, we could avoid writing some of these tests by focusing on the higher layers (e.g. only write the web test for the user registration with duplicate email case), but the lower layers would then be exposed if they were to be reused by a different client (e.g. application services used by a batch client).
So we end up wondering how useful writing all these tests will be and how we can be more efficient in our approach. What is your take on this?
I realize this is more a discussion-type question than one that has a clear and verifiable answer, so if this is not the appropriate forum, would you please direct me to the best forum for these discussions.