Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 88 additions & 12 deletions pkgs/test_reflective_loader/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,100 @@
[![pub package](https://img.shields.io/pub/v/test_reflective_loader.svg)](https://pub.dev/packages/test_reflective_loader)
[![package publisher](https://img.shields.io/pub/publisher/test_reflective_loader.svg)](https://pub.dev/packages/test_reflective_loader/publisher)

Support for discovering tests and test suites using reflection.
Support for discovering and running tests and test suites using reflection.

This package follows the xUnit style where each class is a test suite, and each
method with the name prefix `test_` is a single test.
This package follows an xUnit style where each class can be a test suite.
Test methods within the class are discovered reflectively based on their names or annotations.

Methods with names starting with `test_` are run using the `test()` function with
the corresponding name. If the class defines methods `setUp()` or `tearDown()`,
they are executed before / after each test correspondingly, even if the test fails.
## Usage

Methods with names starting with `solo_test_` are run using the `solo_test()` function.
A test file will typically have a `main` function that kicks off the test loader, and one or more classes annotated with
`@reflectiveTest`.

Methods with names starting with `fail_` are expected to fail.
Here is a simple example:

Methods with names starting with `solo_fail_` are run using the `solo_test()` function
and expected to fail.
```dart
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

Method returning `Future` class instances are asynchronous, so `tearDown()` is
executed after the returned `Future` completes.
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(MyTestClass);
});
}

@reflectiveTest
class MyTestClass {
void test_simpleSuccess() {
expect(true, isTrue);
}

@failingTest
void test_expectedToFail() {
expect(false, isTrue);
}

@skippedTest
void test_skipped() {
// This test won't be run.
}

void setUp() {
// setUp is called before each test.
print('setting up');
}

void tearDown() {
// tearDown is called after each test.
print('tearing down');
}
}
```

To run the tests, you would execute your test file with `dart test`.

### Test Discovery

The `defineReflectiveSuite` and `defineReflectiveTests` functions are used to discover and define tests.

* `defineReflectiveSuite`: This function creates a test suite. It takes a closure as an argument, and within that
closure, you can define tests and other nested suites. This allows you to group related tests together.

* `defineReflectiveTests`: This function tells the test runner to look for tests in a given class. The class must be
annotated with `@reflectiveTest`. The test runner will then reflectively look for methods in that class that are
considered tests (see below).

### Test Suites

Test suites are classes annotated with `@reflectiveTest`. The loader will instantiate this class for each test method,
so tests are isolated from each other.

### Test Methods

The loader discovers tests in a few ways:

* Methods whose names start with `test_` are treated as tests.
* Methods whose names start with `fail_` are treated as tests that are expected to fail.
* Methods whose names start with `skip_` are skipped.

### Annotations

* `@failingTest`: Marks a test that is expected to fail. This is useful for tests that demonstrate a bug that has not
yet been fixed.
* `@skippedTest`: Marks a test that should be skipped and not run.
* `@soloTest`: Can be applied to a test class or a test method to indicate that only this test (or the tests in this
class) should be run. If multiple tests/classes have this annotation, they will all run.

### `setUp` and `tearDown`

If a test class defines a `setUp()` method, it will be run before each test method in that class. If it defines a
`tearDown()` method, it will be run after each test method, even if the test fails. These are useful for setting up and
cleaning up test fixtures. Both `setUp()` and `tearDown()` can be `async` and return a `Future`.

### Asynchronous Tests

If a test method, `setUp()`, or `tearDown()` returns a `Future`, the test runner will wait for the future to complete.
The `tearDown` method (if any) will be executed after the test method and its `Future` completes.

## Features and bugs

Expand Down
Loading