dart-lang / dart-lang/language
Make unit tests a first class citizen
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
This issue came out of a discussion around static metaprogramming and some thoughts I've had on unit testing for a while now.
https://github.com/dart-lang/language/issues/1482
I think it's fair to say that unit tests are considered a critical piece in building any application.
The problem is that building unit tests is difficult, as is maintaining them.
For many projects I'm involved in, it's not uncommon for me to spend more time maintaining the unit tests than I spend on making actual code changes.
This seems highly problematic and I believe this is largely the result of the unit tests being treated as a second-class citizen in dart (as it is in many other languages).
We expect a language to have a debug mode, wherein the language allows things to be done in debug mode that the language won't do in release mode.
In the same way that we have a debug and a profile mode, we should have a test mode.
The current package approach (test, mock, dependency injection) is clearly not adequate as writing tests is a significant labour.
Writing unit tests often (always?) requires us to architect our code around supporting unit tests.
Whilst some may argue that the discipline of writing unit test can improve our architecture, this is not the same thing as a process that as of today, inherently dictates our application architecture.
There are a number of common scenarios that the language could support in a 'test mode' that would reduce or eliminate the need to re-architecture our code and potentially make writing unit tests quicker and less brittle.
I don't claim to have all the answers as to what this might look like but there are a few obvious starting points
1) private methods.
The test mode should allow a unit test to call a private method without any special annotations required on the target library.
This should probably extend to third-party libraries.
2) overload static methods
I recently wanted to overload the `exit()` method to stop calls to it from shutting down my unit test.
If a singleton provides the required solution then I should be able to choose a singleton.
I should be able to scope these overloads to a test or group.
i.e. one unit test overloads the exit() method but another doesn't or does so in a different manner.
3) support for mocking
Using the existing mocking frameworks is ugly and requires an unnecessary amount of code.
I should be able to capture and mock an instance creation that occurs deep in the call tree.
Again, we should be able to scope these mocks.
I'm sure there are other ideas and pain points that we could solve with a 'test mode' built into the language.
# references
https://en.wikipedia.org/wiki/AspectJ
The java AspectJ library provides some interesting concepts in terms of writing an expression that matches functions or classes and allows their behaviour to be altered.
https://github.com/dart-lang/language/issues/1482
Concepts from dart's forthcoming static metaprogramming combined with additional features when running in test mode might also provide some paths forward.
# Summary
Making unit tests a first-class citizen via language support for testing would benefit the entire dart community by:
1) reducing the labour spent on creating/maintaining unit tests
2) remove the need to design architecture that suit the needs of unit tests over and above the applications problem space.
3) potentially increase the use of unit tests by making them easier to build and maintain
Contributor guide
Research direction
Start by reading the linked static metaprogramming discussion at dart-lang/language#1482 and comparing it with the stated test, mock, and dependency-injection limitations. The issue names no files or tests; done would require a settled language design covering private access, scoped method overloads, and scoped instance mocking in a test mode.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart
- Domain
- testing
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100