David De Vargas
Implementation (or Unit) testing
Brings a test over a fundamental unit of code, usually functions or classes. It’s highly attached to how the code was written.
Test algorithm
Get a function or method.
Insert inputs and call it.
Compare the response.
Use case
Review code quality.
Functional or Behavioral Testing
Tests how users use our software and not our internal implementation as unit tests. Includes all relevant components that involve certain user behavior.
Test algorithm
Builds a virtual representation of a UI element.
Simulate a user interaction over the element: clicks, scroll, mouse over, etc.
Compares the behavior with the expected result.
Use case
Meet user stories, 1 user story ~ 1 functional testing.
Visual Testing
Evaluate the UI according to the expected design, works over the user interface looking at what happens when clicking a button or scrolling a page, etc.
Test algorithm
Builds a virtual representation of a UI element.
Simulate a user interaction over the element: clicks, scroll, mouse over, etc
Compare the response visually with the original design.
Use case
Sync UI developers and designers.
Integration (or API) Testing
Focused on checking data communication between modules of code, and API communication.
Test algorithm
Get an API.
Call it.
Check structure and content.
Use Case
Validates the data structure and its content from our APIs.
Acceptance Testing
It's performed by users after testing the system and before making it available for actual use on market.
Test algorithm
People outside the developer team use the app in production.
Gather real metrics.
Compare it with business metrics.
Use case
Validates if business requirements are met.
Types of acceptance tests
Internal Acceptance (or Alpha) Testing is performed by members of the organization that developed the software but who are not directly involved in the project.
Customer Acceptance Testing: performed by the customer of the organization that developed the software.
User Acceptance (or Beta) Testing is performed by the end-users of the software.
Test-Driven Development (TDD)
As we saw, testing doesn’t require code implementation to be done, TDD is the practice of writing our tests at first and later writing the code.
Steps:
Write “shell” component or feature.
Write the tests and import your shell component into them.
Fail the tests.
Write code until it passes the tests.
Benefits:
Testing neglect is avoided and requirements are enforced by ensuring that your code conforms to testing and not vice versa, and also helps to write better code from the beginning making us think in requirements before we write a single line of code.
Good Practices
So far, doing automatic testing sounds like the best solution, and it is, but a bad implementation can turn it into a nightmare. I trust that by having clear concepts, following the next suggestions, and practicing a little (with the tool you want), you will avoid the most common mistakes.
For testing
Run tests in isolation between other tests and other components. One file per component, one or more tests per feature, and one test for one requirement.
Test edge cases and error paths not just happy ones, because we want our tests to cover a wide range of scenarios.
Establish a domain and range (inputs & outputs) for each feature we are testing, in this way, when a certain input is received we can be sure of the type of result that we can expect.
For Coding
Apply SOLID principles to write, clean, modular, and descriptive software, avoiding:
Swamp of global variables.
Pointer soup.
Side effects (as possible).