Tests
Manual Tests
Are important, especially for key users acceptance. It can also enrich automated tests, since we cannot think in all possible scenarios.
Must be complementary and don't guarantee that there won't be future regressions.
Automated Tests
Tests must have a well defined output, which is valid or not, and this will pass or fail the test.
There must not be dependencies between tests, they must be able to be executed separately.
Structure
A test can be separated in 3 steps.
Given (Arrange)
The definition of all necessary information to execute the behavior to be tested. (Data input)
When (Act)
Where you execute the behavior.
Then (Assert)
Where you compare the return information with the expected one. (Basically is the expect
)
Coverage
Coverage in tests means the amount of code that the tests run on. It is not related to success
or failure
percentage.
Types of Tests
Unit Test
They are not necessarily unitary (solitary), they may or may not involve more than one class.
They must not interact with external resources like:
Database.
API.
File system.
They cover just the domain layer.
They are punctual and quick tests.
Data validation is usually done in here.
Integration Tests
Test components belonging to multiple layers and usually involves external resources.
May use Stubs, Mocks, to avoid the use of low-level layers.
Usually cover the application layer. (Use Cases)
The objective is to test the application layer and inner layers. (Not outside layers)
More expensive.
E2E Tests (End-to-End)
Are extremely fragile and break with ease.
Replicate the entire user experience, every way he interacts with the system.
May depend on tools like:
Selenium,
Cypress,
Playwright,
Other variations evolving WebDriver or Puppeteer.
Very slow.
Test Patterns
If you can only test by using these patterns may indicate that the design must improve.
Stub
Are objects that return fixed answers, defined for a specific test, because of performance or security.
Ex.: Avoiding your tested usecase to invoke a Gateway that sends emails. (With Stubs you overwrite inline (at the test level) the Gateway behavior without having to implement a Fake instance)
You only control de returned data from the stubed function.
Stubs can become difficult to use if you have to stub a lot of methods, and they require data from one another.
A simpler solution then would be to use a Fake
.
Spy
Are objects that "spy" on the execution of other methods and save the results to be checked later.
They don't overwrite behavior, you only tap to the execution. (You hove no control over the function call)
Ex.: Checking in your tested usecase, if it called that spied method. Or which data it returned or was given.
Mock
Are objects similar to Stubs and Spies.
But you can control the function call:
Also what parameters it will be called.
And you can control what it returns.
Dummy
Are objects that are created only to complete the list of parameters to invoke a specific method.
Ex.: The code requires you to provide arguments, but it does not have any relevance in the business rule.
Like specifying dummy data for a function.
Fake
Are objects that have implementations that simulate the real instance operation, used in production.
Ex.: Writing a in-memory database implementation, that follows the same contracts as the default one.
A good code design is required to use fakes, which can/may be simpler depending on the situation.
Fake
require more work, since you will have create the Fake class, instanciate it in the test and inject them into the dependant methods.
Last updated