Skip to content

History

Showing with 194 additions and 0 deletions.
  1. +23 −0 Getting-Started.md
  2. +13 −0 Home.md
  3. +158 −0 Matrix-Syntax.md
23 changes: 23 additions & 0 deletions Getting-Started.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,26 @@ fn testing_function(input: Type) -> ResultType {
```

Test case syntax can be found [here](Syntax)

## Test Matrix

* Import `test_matrix` to the scope you are using it in:

```rust
use test_case::test_matrix;
```

* Add a test matrix to your function:

```rust
#[test_matrix(
[-2, 2],
[-4, 4]
=> output_matcher
)]
fn testing_function(input_1: i8, input_2: i8) {
body!()
}
```

Test matrix syntax can be found [here](Matrix-Syntax)
13 changes: 13 additions & 0 deletions Home.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,16 @@ fn tested_function(s: &str) -> &str {
todo!()
}
```

[Matrix](Matrix-Syntax) Example:

```rust
#[test_matrix(
["maybe", "works"],
1..=10
==> "expected result"
)]
fn tested_function(a: &str, b: u16) {
todo!()
}
```
158 changes: 158 additions & 0 deletions Matrix-Syntax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
Test matrix attribute can be defined as:

```
#[test_matrix(
(argument_inputs),+
(=> modifiers output_matcher)?
)]
```

_Test case comment/description is explicitly not allowed for `test_matrix`_

# Inputs
The number of inputs mutch match the number of tested function arguments. Each
input can be one or more possible values for the argument.

## Input Syntax

### List of values
A list in **array** (`[x, y, ...]`) or **tuple** (`(x, y, ...)`) syntax. The
values can be any valid [expression](https://doc.rust-lang.org/reference/expressions.html).
This includes string (`"value"`) and numeric (`42` or `42usize`) literals,
constants (`FORTY_TWO`), function calls (`sqrt(FORTY_TWO)`), arithmetic
(`FORTY_TWO / 2`) and many other possibilities.

<details>

<summary>Common Errors</summary>

#### Literal values

Literal values must be all of the same type. Mixed lists will generate an macro usage error:

```sh
error: All literal values must be of the same type
--> src/lib.rs:5:13
|
5 | ["one", 1, true,]
| ^
```

#### Expressions

Other kinds of expressions must return the same type as the test function
argument. A mismatch between expression return type and function argument type
will generate a compiler error pointing to the macro argument as well as the
test function:

```sh
error[E0308]: mismatched types
--> src/lib.rs:33:15
|
33 | #[test_matrix(USIZE_CONST)]
| --------------^^^^^^^^^^^--
| | |
| | expected `i8`, found `usize`
| arguments to this function are incorrect
|
note: function defined here
--> src/lib.rs:34:4
|
34 | fn wrong_argument_type(x: i8) {
| ^^^^^^^^^^^^^^^^^^^ -----
help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
|
33 | #[test_matrix(USIZE_CONST.try_into().unwrap())]
| ++++++++++++++++++++
```
</details>
### Range
A bounded numeric [range expression](https://doc.rust-lang.org/reference/expressions/range-expr.html)
(e.g. `0..100` or `1..=99`), which will generate argument values for all
integers in the range. Unbounded ranges (e.g. `..100`, `..=99`, or `1..`) are not
allowed, as they would generate an infinite number of test cases.
<details>
<summary>Common Errors</summary>
#### Unbounded range
A provided range must have a beginning and end.
```sh
error: Unbounded ranges are not supported
--> src/lib.rs:18:16
|
18 | #[test_matrix(1..)]
| ^
```
#### Non-literal range bound
Values must be integer literals. A macro error will be generated for non-literal expressions:
```sh
error: Range bounds can only be an integer literal
--> src/lib.rs:13:18
|
13 | #[test_matrix(1..END)]
| ^^^
```
</details>
### Expression (Single Value)
A single expression, which can be used to keep one argument constant while
varying the other test function arguments using a list or range. Expressions
must return a type that is the same as the function argument in that position.
**Note:** Expressions that return `Vec`, `array`, or `tuple` will pass that
type to the test function. The list entries are not expanded into separate test
cases as with the [literal list syntax](#list-of-values) above.
# Output
`test_matrix` uses the [same validation mechanism](Syntax#output) as `test_case`. The validation will be applied to every test case generated by the matrix, regardless of input. See the [`test_case` **Output** documentation](Syntax#output) for details.
# Multiple Matrices
It is possible to use the `test_matrix` macro multiple times on a test function to test separate matrices, perhaps under different configurations:
```rust
const CONFIG_BIG: Config { ... };
const CONFIG_LITTLE: Config { ... };
#[test_matrix(
CONFIG_BIG,
[1000, 10000, 100000],
["alpha", "beta"]
)]
#[test_matrix(
CONFIG_LITTLE,
[1, 10, 100],
["alpha", "beta"]
)]
fn test_function(config: Config, n: u64, sector: &str) {
todo!()
}
```
It is also possible to combine the `test_matrix` macro with the `test_case`
macro to test a matrix of values and add some specific edge cases:
```rust
#[test_matrix(
0..100,
[2, 3, 4]
)]
#[test_case(0, 0 => panics ; "panics on all zeroes")]
fn test_function(x: u64, y: u64) {
todo!()
}
```
The order of `test_case` and `test_matrix` is not significant; the same set
of test cases will be generated.