docs/development/testing/README.md
OpenProject uses automated tests throughout the stack. Tests that are executed in the browser (angular frontend, RSpec system tests) require to have Chrome installed. To ensure we deliver high quality code to our customers, it's essential to conduct various types of tests.
| Topic | Content |
|---|---|
| Testing architecture (this page) | Overview of the architecture and involved parties regarding testing |
| Continuous testing workflow | Overview of our CI and Continuous testing pipelines and how to debug them |
| Running tests locally | Guides on how to run tests on your machine or on Docker |
| Handling flaky tests | Guides to identify, debug, and fix tests that intermittently pass or fail |
Testing OpenProject is distributed between different roles and members, depending on the testing task.
Functional testing ensures that the application works against the set of requirements or specifications. Tests should therefore make sure all the acceptance criteria are met.
The following types of functional tests are used at OpenProject.
| Type | Description | Examples, References |
|---|---|---|
| Unit tests | Test individual components of OpenProject using RSpec. Involves mocking or stubbing dependent components | e.g, Model specs under spec/models |
| Integration tests | Testing the integration of multiple components, but still in their isolation without testing the entire software stack | controller, requests, service integration specs, e.g., spec/services/**/*_integration_spec.rb |
| Feature / end-to-end tests | Tests of the entire Rails application stack and all necessary dependent components (routing, controllers, database access, permissions, and responses). Performed in RSpec using Capybara feature specs. | |
| External third-party service requests and responses are recorded for testing (e.g., nextcloud integration) | spec/features | |
| Smoke tests | Automated and manual tests to ensure the main application features and happy paths are working as expected (e.g., packaging or dockerization tests, manual smoke tests by QA) | Docker test workflow under .github/workflows/docker.yml |
| Sanity and regression tests | Manual testing of affected or relevant components made after changes or bug fixes to the application. Performed by QA. | e.g., testing the critical path of creating work packages after a bug fix has been made in that data model |
| Manual execution of test plan defined by QA | ||
| Acceptance tests | Final phase of manual testing where the system is evaluated against predefined requirements to ensure it meets user and stakeholder expectations before deployment. | Manual interactions with customers and stakeholders to identify whether we're building the correct part |
Unit testing concerns testing of isolating individual components of the application, such as individual methods within a model, service, or library, in order to verify that they perform as expected under various conditions. OpenProject uses RSpec for writing unit tests / specs.
Key objectives and effects
Best practices
Follow the Arrange-Act-Assert (AAA) Pattern
Keep examples of unit specs simples and descriptive
Write tests during or before development, not as an afterthought
Test the entire range of potential inputs, including negative tests and validation of potentially malicious user input.
Negative testing consists of test cases which define how software reacts to user’s invalid input or unexpected behavior. The aim is not only to prevent the application from crashing but to improve quality by specifying clear and understandable error messages so that users know what kind of input is expected and correct.
Avoid calling the database if not necessary
Use FactoryBot to set up test data in a structured, but randomized way to prevent brittle tests
Mock external components and services, and ensure you test the boundaries of the associated components
References
Integration tests focus on the interactions between different components of OpenProject to ensure they work together to deliver a specific functionality. OpenProject uses RSpec to perform integration tests to simulate real-world user behavior. In contrast to system tests, integration tests still leave out some assumptions or characteristics of the application (e.g., not running tests in an instrumented browser instance).
In Rails, the difference between integration tests and feature tests can be blurry. At OpenProject, we assume every test that involves an instrumented browser instance is a feature spec. Integration tests can be request or controller specs, or specs in other folders explicitly marked as integration, meaning it will not use mocking to separate the involved components.
Key objectives and effects
Best practices
Feature tests at OpenProject drive a browser instance to act as if a user was operating the application. This includes logging in, setting session cookies, and navigating/manipulating the browser to interact as the user.
Key objectives and effects
End-to-end testing: Validate the interaction between the entire stack of the application, including the frontend and backend, to ensure they work as expected.
User experience verification: Simulate real-world user behavior and ensure that the application behaves as expected from a user's perspective.
Increased confidence: In Rails applications, only feature tests give you the entire picture of the application, especially when frontend code is interacting with the backend.
Responsiveness and compatibility: Verify that the application's user interface behaves consistently across various browsers, languages, and screen sizes.
Best practices
within, find, etc.), meaningful selectors, and asynchronous handling to make tests more readable and robust.let_it_be / shared_let and other improvements from the test-prof gemSmoke tests are automated and manual tests to ensure the main application features and happy paths are working as expected. At OpenProject, all installation methods are automatically tested using smoke tests. Packaging processes test all distributions for successful installation of OpenProject. We run the released docker image for setting up and accessing OpenProject.
Key objectives and effects
Best practices
References
Sanity and regression tests are manually performed tests by QA for relevant components on a stabilized version, e.g., the developed new features or components of an OpenProject release. A sanity test is a subset of a regression test, which evaluates the entire application prior to a release or production deployment.
Key objectives and effects
Best practices
Usage at OpenProject
For writing and executing manual sanity and regression testing, especially focusing on functional requirements, one of the tools in use at OpenProject is TestLink to achieve the following goals:
References
Acceptance testing is the final phase of testing where the extension to the OpenProject application is evaluated against predefined requirements to ensure it meets user and stakeholder expectations before deployment.
Acceptance tests evaluate both functional and non-functional requirements.
Key objectives and effects
Best practices
Non-functional testing goes beyond the functionality of the product and is aimed at end-user experience. Test cases should hence make sure to define what is expected in terms of security, performance, compatibility, accessibility etc.
Examples for non-functional test cases: software should be compatible with most used desktop and mobile browsers, as well as operating systems; all the actions can be performed with keyboard navigation; page loading should take no more than X seconds; users who lost access should no longer be able to login etc.
| Type | Description | Examples, References |
|---|---|---|
| Stress and performance tests | (Half-)automated or manual testing of the response of the application during higher load, or expected upper boundaries of customer-defined data | e.g., running and evaluating new query plans on existing, anonymized or simulated data that matches potential or known performance bottlenecks |
| Security tests | Automated or manually crafted test cases for evaluating application security by assuming the role of an attacker, e.g., by providing malicious user input or trying to break the application. | Statical and automated code scanning (CodeQL, Brakeman), defined test cases for verifying security related input as defined in the secure coding guidelines. |
| Installation / upgrade tests | Automated and manual installation tests of OpenProject | Packaged installation build tests for various distributions, Docker installation smoke tests for verifying correct startup and basic operation of the container. |
| Usability tests | Evaluating the UX of the application as defined and in comparison to the requirements. Involves QA, Product, Customer. | e.g., verifying common use-cases as defined in the requirements in an early development stage (such as a PullPreview deployment), or on a pre-released version of the application. |
| Accessibility tests | Evaluating the accessibility of the application according to WCAG AA and similar standards | Performing automated keyboard navigation tests. |
| Manually executing screen readers to ensure application can be used. |
Identify and prevent common causes of bottlenecks in the application. As OpenProject is a software where a lot of information might come together and presented in a very flexible manner, performance is an ever-present concern and consideration for the developers.
Key objectives and effects
Best practices
Automated or manual security tests for OpenProject are evaluating common weaknesses of web applications and follow the best practices of the secure coding guidelines.
Key objectives and effects
Best practices
OpenProject employs a number of automated tests for installation testing. Packaged installation build tests for various distributions, Docker installation smoke tests for verifying correct startup and basic operation of the container.
Upgrade tests are manually performed for major code changes and data migrations on pre-release candidates to ensure migrations are working as expected. The OpenProject Community instance also serves as an early release candidate to allow early testing and feedback.
Key objectives and effects
Best practices
When new features or changes to the application are available on our Edge or Community environments, product team members, customers, and community users can provide usability feedback on how the change is perceived.
Key objectives and effects
User-friendliness: Evaluate how easily end-users can navigate and perform tasks within the application, focusing on intuitiveness and accessibility.
Increased user satisfaction and adoption: Better usability promotes a higher rate of user adoption and lowers abandonment rates.
Error handling and messages: Assess the software's ability to prevent, catch, and handle errors in a way that is informative and non-intrusive for the user.
Consistency and standards: Ensure that the application's UI and functionality conform to common design and usability standards, promoting user familiarity.
Reduced support costs: Intuitive and user-friendly designs decrease the volume of help desk or support questions.
Best practices
OpenProject strives to be accessible for all users while also retaining a high usability. In web applications, these two requirements can sometimes be a seemingly contradictory requirement, especially when animations or modern functionalities of browsers are used.
Key objectives and effects
Best practices
References