diff --git a/docs/10-contribute.md b/docs/10-contribute/01-contribute.md similarity index 99% rename from docs/10-contribute.md rename to docs/10-contribute/01-contribute.md index f104d911..fa5e4494 100644 --- a/docs/10-contribute.md +++ b/docs/10-contribute/01-contribute.md @@ -5,6 +5,7 @@ Serverpod is built by the community for the community. Pull requests are very mu
## Roadmap + If you want to contribute, please view our [roadmap](https://github.com/orgs/serverpod/projects/4) to make sure your contribution is in-line with our plans for future development. This will make it much more likely that we can include the new features you are building. You can also check our list of [good first issues](https://github.com/serverpod/serverpod/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). :::important @@ -109,7 +110,6 @@ If you are contributing new code, you will also need to provide tests for your c Feel free to post on [Serverpod's discussion board](https://github.com/serverpod/serverpod/discussions) if you have any questions. We check the board daily. - ## Repository overview Serverpod is a large project and contains many parts. Here is a quick overview of how Serverpod is structured and where to find relevant files. @@ -142,4 +142,4 @@ These are 1st party modules for Serverpod. Currently, we maintain an authenticat ### `integrations` -These are integrations for 3rd party services, such as Cloud storage. \ No newline at end of file +These are integrations for 3rd party services, such as Cloud storage. diff --git a/docs/10-contribute/02-testing-guideline.md b/docs/10-contribute/02-testing-guideline.md new file mode 100644 index 00000000..54bcc2ea --- /dev/null +++ b/docs/10-contribute/02-testing-guideline.md @@ -0,0 +1,258 @@ +# Serverpod Testing Philosophy + +## Overview + +At Serverpod, our core testing philosophy revolves around achieving the following goals: + +- **Readable and Self-Explanatory Tests** – Tests should be easy to understand at a glance. Descriptions must clearly convey the purpose and expected outcome without needing to inspect the test's internal implementation. +- **Resilient to Refactoring** – Tests should not break due to internal refactoring. As long as the external behavior remains consistent, tests should pass regardless of code structure changes. +- **Focused on Behavior, Not Implementation** – We prioritize testing how the code behaves rather than how it is implemented. This prevents unnecessary coupling between tests and production code, fostering long-term stability. +- **Easy to Maintain and Expand** – Tests should be simple to update or extend as the product evolves. Adding new features should not require widespread changes to existing tests. +- **Effective at Catching Bugs** – The primary goal of testing is to identify and prevent bugs. Our tests are crafted to cover edge cases, ensure proper functionality, and catch potential regressions. + +By adhering to the following principles, we ensure that our test suite remains a valuable and reliable asset as our codebase grows. + +This document outlines Serverpod's approach to testing code. It serves as a guide for writing effective, maintainable, and meaningful tests across all our projects. + +## Key Principles + +### 0. Test Independence + +- **Tests should be completely independent of one another.** +- The outcome of a test must never depend on any other test running before or after it. +- The order in which tests are executed **should not matter.** +- Running a single test in isolation must produce the same result as running it alongside others. +- **Exception to the rule:** e2e and integration tests. In scenarios where an external state (like a shared database) is involved, tests may require concurrency mode 1 to prevent interference. But each test should start and end in a clean state. + +### 1. Clear and Descriptive Test Descriptions + +- **Test descriptions should be understandable without reading the test code.** +- If a test fails, the description alone should make it clear what went wrong. +- **Format:** Descriptions follow the "Given, When, Then" style. + +**Example:** + +```dart +// Given a user with insufficient permissions +// When attempting to access a restricted page +// Then a 403 Forbidden error is returned +``` + +### 2. Focus on Single Responsibility + +- Each test should **only test one thing**. +- **Avoid** bundling multiple independent checks into a single test. +- It is acceptable to **repeat the same precondition and action** across tests to ensure each aspect is tested individually. + +**Example:** + +```dart +// Good - Tests are split +test('Given an empty list when a string is added then it appears at the first index', () { + final list = []; + list.add('hello'); + expect(list[0], 'hello'); +}); + +test('Given an empty list when a string is added then list length increases by one', () { + final list = []; + list.add('hello'); + expect(list.length, 1); +}); + +// Bad - Multiple independent checks in one test +test('Add string to list and check index and length', () { + final list = []; + list.add('hello'); + expect(list[0], 'hello'); + expect(list.length, 1); +}); +``` + +- Multiple `expect` statements are not necessarily against this rule. However, they must check values that are interdependent and only meaningful when evaluated together. + +**Example:** + +```dart + test('Given a missing semicolon when validated then the entire row is highlighted', () { + final code = 'final a = 1'; + final result = validateCode(code); + + expect(result.span.start.column, 1); + expect(result.span.end.column, 12); + expect(result.span.start.line, 1); + expect(result.span.end.line, 1); + }); +``` + +- In this case, verifying both the start and end positions of the `SourceSpanException` is essential because they collectively describe the error location, and their correctness is interdependent. + +\*Note: SourceSpanException is an object that describes a code error in a source file. See: \*[*https://api.flutter.dev/flutter/package-source\_span\_source\_span/SourceSpanException-class.html*](https://api.flutter.dev/flutter/package-source_span_source_span/SourceSpanException-class.html) + +### 3. Pure Unit Testing + +- **Unit tests should avoid mocking and side effects.** +- Production code should push side effects **up the call stack**, allowing tests to cover pure methods. +- **Test the logical feature/unit** rather than a single method or class. + +**Example:** + +```dart +// Avoid mocking HTTP requests directly, test the logic that processes the response +Future