Supercharge your Dart testing with parameterized_test! Built on top of the dart test package, this JUnit ParameterizedTest inspired package wrap around group
and test
to take your testing to the next level!
- ✅ Run a test multiple times based on provided parameter list.
- ✅ Built on top of dart test package.
- ✅ Type cast test parameters used in the tests.
- ✅ Include test options for parameter_test.
- ✅ Include test options per parameter.
dev_dependencies:
parameterized_test: [latest-version]
Instead of creating a group
test with multiple of the same test
and different parameters, you can now use parameterizedTest
and supply it list of test parameters to run the same test with multiple times.
Specifying a parameterized test is almost the same as normal test. It has all the same parameters as a normal test like: skip
or testOn
etc.
The only difference is that you need to provide a list of test values and a function that takes the same amount of arguments as the test values.
For example:
parameterizedTest(
'Fruit name matches length',
// List of values to test
[
// parameters for the test
['kiwi', 4],
['apple', 5],
['banana', 6],
['pineapple', 9],
],
// Test function accepting the provided parameters
(String fruit, int length) {
expect(fruit.length, length);
},
);
This parameterizedTest
will create a group
with 4 test
inside it. Each test will run the test function with the provided parameters.
- Fruit name matches length (group)
- [ 'kiwi', 4 ] (test)
- [ 'apple', 5 ] (test)
- [ 'banana', 6 ] (test)
- [ 'pineapple', 9 ] (test)
There is also a parameterizedGroup
which is basically the same as parameterizedTest
but instead of creating a group
that runs a test
multiple times, it creates a group
that runs a group
multiple times.
Here you still need to provide a test
. This can be useful if you want to have nested groups of tests.
Besides accepting a list of test values, you can also provide a setUp
and tearDown
function to run before and after each test.
If you want to add test options to a specific parameter you can do so by using the options
extension on List
. This will allow you to add test options like skip
or testOn
to a specific parameter.
For example:
parameterizedTest(
'Fruit name matches length',
// List of values to test
[
// parameters for the test
['kiwi', 4],
['apple', 5].options(skip: 'Apple is not ripe yet'),
['banana', 6],
['pineapple', 9],
],
// Test function accepting the provided parameters
(String fruit, int length) {
expect(fruit.length, length);
},
);
This will create a group
with 4 test
inside it. The second test will receive the provided test options and will be skipped in this case.
By default, the test description contains the test value used within the tests. you can override this by using customDescriptionBuilder
.
When normally running parameterized tests with description 'My parameterized test' and the values [['first', 'second', true], ['third', 'fourth', false]]
the test description output looks something like this:
My parameterized test [ 'first', 'second', true ]
My parameterized test [ 'third', 'fourth', false ]
When defining a customDescriptionBuilder
like this:
...
customDiscriptionBuilder: (groupDescription, index, values) => '🚀[$index] $groupDescription: <<${values.join('|')}>>',
...
The output will look like this:
My parameterized test 🚀[1] My parameterized test: <<first|second|true>>
My parameterized test 🚀[2] My parameterized test: <<third|fourth|false>>
Note: the first 'My parameterized test' is because parameterized tests make use of a group test. Most IDE's will group this for you and only show the second part.
parameterizedTest(
'Example of list of single values',
[
1,
2,
3,
],
(int value) {
final result = value < 4;
expect(result, true);
},
);
parameterizedTest('Example of list of multiple values', [
[0, 1, 1],
[1, 1, 2],
[1, 2, 3],
[2, 2, 4],
], (int value1, int value2, int sum) {
expect(value1 + value2, sum);
});
parameterizedTest('Example of a list with complex object', [
[DateTime(2024, 4, 12), 5],
[DateTime(1969, 07, 20), 7],
], (DateTime dateTime, int expectedWeekday) {
expect(dateTime.weekday, expectedWeekday);
});
enum TestEnum {
one(3),
two(3),
three(5);
const TestEnum(this.myLength);
final int myLength;
}
parameterizedTest(
'Example using enum as value',
TestEnum.values,
(TestEnum testEnum) {
expect(testEnum.name.length, testEnum.myLength);
},
);
List<dynamic> provideData() {
return [
[0, 1, 1],
[1, 1, 2],
[1, 2, 3],
[2, 2, 4],
];
}
parameterizedTest(
'Example of list of values from function',
provideData(),
(int value1, int value2, int sum) {
expect(value1 + value2, sum);
},
);
parameterizedTest(
'Example with setup and teardown ',
[
['kiwi', 4],
['apple', 5],
['banana', 6],
],
(String word, int length) {
expect(word.length, length);
},
setUp: () {
print('Setup everything I need for testing');
},
tearDown: () {
print('tear it down again');
},
);
parameterizedTest(
'Example using a async test',
[
100,
200,
300,
],
(int value) async {
final millis = DateTime.now().millisecondsSinceEpoch;
await Future<void>.delayed(Duration(milliseconds: value));
final passed = DateTime.now().millisecondsSinceEpoch - millis;
expect(passed >= value, true);
},
);
Note: This is a example test to showcase async tests are also possible. But this is not a good practice to use a delay like this in a test. Running this test will take longer. This could be fixed by using a package like fake_async.
Its also possible to combine parameterizedTest for example with the csv package.
parameterizedTest('Example of CSV data',
const CsvToListConverter().convert('kiwi,4\r\napple,5\r\nbanana,6'),
(String fruit, int length) {
expect(fruit.length, length);
});
It's just a simple wrapper to easily execute tests multiple times with different values. Feel free to leave some feedback or open a pull request :)