Skip to content

Commit eb0fb19

Browse files
vzarytovskiibaronfel
authored andcommitted
Added readme file with testing proposal
1 parent 6d6e97f commit eb0fb19

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

tests/README.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# F# Testing proposal
2+
3+
## Why do we test
4+
5+
* To prevent regressions (behavioral, performance).
6+
* To have a quicker debug feedback (thus, find problems quicker).
7+
* To verify conformance to language spec (API contract testing).
8+
* To have IL verification (both read and write).
9+
* To have a quicker design feedback.
10+
* To document behavior.
11+
12+
## Goals
13+
14+
* Use one standardized testing framework across all of test projects, and get rid of custom old solutions (FSharpQA and Cambridge suites).
15+
* Have tests restructured the way, that they are easy to discover.
16+
* Have tests building and running on all supported platforms (Windows, macOS and Linux) and different frameworks (with exceptions when this is not applicable).
17+
* Make it easy to run tests using standard .NET instruments (dotnet cli, test explorer, etc.).
18+
* Leverage standard .NET testing platform and use all its benefits, suck as live unit testing, code coverage collecting, dead code elimination, etc.
19+
20+
## Framework for testing
21+
22+
The following test frameworks and libraries will be used for new test projects **[xUnit Test Framework](https://xunit.net/), [FluentAssertions](https://fluentassertions.com/) (+ [FsUnit](https://fsprojects.github.io/FsUnit/) and [FsCheck](https://github.com/fscheck/FsCheck) when needed)**. All existing NUnit test suites will be migrated to xUnit.
23+
24+
**Justification:**
25+
26+
* **xUnit** is an extensible, TDD adherent, testing framework, which was successfully adopted by many .NET engineering teams, including Roslyn, AspNetCore, EFcore, etc, has a "cleaner" approach for writing test suites (i.e. class constructor for setup, implementing IDisposable for teardown, as oppose to custom attributes). More info [here](https://xunit.net/docs/comparisons).
27+
* **FluentAssertions** makes it easier to write scoped assertions, provides better error messages.
28+
29+
**Alternatives:** NUnit, MSBuild, Expecto
30+
31+
### Tests categorization
32+
33+
#### New tests should be grouped based on two factors: test type (1) + test category and subcategory (2)
34+
35+
1. **Test type**:
36+
**Determines what type of test is it:**
37+
* __Functional tests__:
38+
* __Unit Tests__: a lightweight testing for smaller modules, functions, etc.
39+
* __Examples__: Testing individual parts/functions of lexer, parser, syntax tree, standard library modules, etc.
40+
* __Subgroups__: there should be a separation between testing private and public parts of each module (i.e. compiler tests for private and public API should be in separate test projects).
41+
* __Component Tests__: testing for bigger parts of compiler.
42+
* __Examples__: Tests for the compiler components as whole, such as Code generation, IL Generation, Compiler optimizations, Type Checker, Type Providers, Conformance, etc.
43+
* __Integration and End2End Tests__: testing of F# compiler & tooling integration, as well as e2e experiences.
44+
* __Examples__: VS Integration, .NET Interactive integration, LSP integration. Integration with dotnet CLI, project creation, building, running.
45+
* __Non-functional tests__:
46+
* __Load and Stress Tests__: testing for high level modules/components to understand peak performance and potentially catch any performance regressions.
47+
* __Examples__: measuring compile, build, link times for the compiler, individual functions (i.e. data structures sorting, traversing, etc.).
48+
1. **Test category and subcategory**: Tests (sub)categories shall be determined by the project, library, module, and functionality tests are covering.
49+
50+
#### Examples
51+
52+
* F# compiler component test which is verifying generated IL for computation expression will have category `Compiler` and subcategories `EmittedIL` and `ComputationExpressions`.
53+
* F# compiler service unit test which is testing F# tokenizer, will have category `Compiler.Service` and subcategory `Tokenizer`.
54+
55+
Please, refer to [File and project structure](#File-and-project-structure) for more information on how tests will be organized on the filesystem.
56+
57+
## File and project structure
58+
59+
### Naming schema
60+
61+
The proposed naming schema for test projects is: `FSharp.Category.Subcategory.TestType`, where
62+
`Category.Subcategory` is either a corresponding source project, or a more generic component (e.g. `Compiler`, `Compiler.Private` or more granular `Compiler.CodeGen`, `Compiler.CodeGen.EmittedIL` if category or subcategory project becomes too big, etc.) and `TestType` is the type of the test (one of `UnitTests`, `ComponentTests`, `IntegrationTests`, `LoadTests`).
63+
64+
### Projects organization
65+
66+
Please refer to the "[Naming schema](#Naming-schema)" section above for more information on the projects naming.
67+
68+
New test projects will be grouped by category and test type, all subcategories are just test folders/files in the test project.
69+
70+
* __Examples__: Having test project organized like:
71+
> `tests/FSharp.Compiler.ComponentTests/CodeGen/EmittedIL/BasicTests.fs`
72+
> `tests/FSharp.Compiler.ComponentTests/CodeGen/StringEncoding/StringTests.fs`
73+
> `tests/FSharp.Compiler.ComponentTests/Optimizations/Inlining/InliningTests.fs`
74+
75+
Will result in one test dll "`FSharp.Compiler.ComponentTests.dll`" which will contain all the subcategories of tests.
76+
* **Notes**:
77+
* This will result in reduced fragmentation of tests, all the tests files are under one big category, easier to understand what each component/unit test suite covers, less confusion in test classification for new tests.
78+
* If some categories (or subcategories) will become big enough - they can be factored out to a separate project.
79+
80+
### Test Utilities/Helpers
81+
82+
For all new and migrated tests, any common/helper functionality shall be factored out to a separate project - `FSharp.Test.Utilities`.
83+
84+
## New tests
85+
86+
* All new tests should be created in the new projects only.
87+
* All new tests should contain a brief docstring description of what is being tested, link to an issue if applicable.
88+
* All new tests should be categorized using xUnit's `Trait`, based on their `Category` and `Subcategories`.
89+
90+
## Migrating existing tests
91+
92+
Existing FSharpQA and Cambridge need to be migrated to corresponding test projects: component-style tests to the `FSharp.Compiler.ComponentTests` and unittest-style tests - `FSharp.Compiler.UnitTests`, `FSharp.Compiler.Private.Scripting.UnitTests`, `FSharp.Build.UnitTests`, etc.
93+
94+
## Next steps
95+
96+
* [**In Progress**] Move `FSharp.TestHelpers` to `FSharp.Test.Utilities`.
97+
* [**In Progress**] Create initial test projects structure for new tests (`FSharp.Compiler.ComponentTests`).
98+
* [**In Progress**] Migrate existing `NUnit` tests to xUnit.
99+
* [**In progress**] Change build scripts to run new suites as well as old ones.
100+
* Start migration of existing (namely, FSharpQA and Cambridge) suites to xUnit-based projects.
101+
102+
## Open questions:
103+
104+
* As far as I know, [FSharp.Compiler.Service](https://github.com/fsharp/FSharp.Compiler.Service) is dependant on some of the F# compiler tests. Does it have to be changed as well?
105+
106+
## Other
107+
108+
Related issues: (https://github.com/dotnet/fsharp/issues/7075)
109+
110+
You can find this document under 'tests/README.md'.
111+
112+
**I would like to hear some feedback the community, so we can quickly re-iterate over it (if needed), and start working :)**

0 commit comments

Comments
 (0)