Skip to content

Add check(…), run(…) & run_tests(…) as supplement to expand(…) #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
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
10 changes: 7 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,23 @@ Please make sure to add your changes to the appropriate categories:

### Added

- n/a
- Added `struct BuildTestSuite`.
- Added `struct ExpandTestSuite`.
- Added `fn check(…) -> BuildTestSuite` crate-level function.
- Added `fn run(…) -> BuildTestSuite` crate-level function.
- Added `fn run_tests(…) -> BuildTestSuite` crate-level function.

### Changed

- n/a
- Changed return type of `fn expand(…)` crate-level function from `-> TestSuite` to `-> ExpandTestSuite`.

### Deprecated

- n/a

### Removed

- n/a
- Removed `struct TestSuite` (by marking it as `pub(crate)`).

### Fixed

Expand Down
129 changes: 85 additions & 44 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,89 @@ cargo install --dev tryexpand

Then under your crate's `tests/` directory, create `tests.rs` file containing calls to `tryexpand::expand()` and populate the `tests/expand/pass/`, `tests/expand/checked_pass/` and `tests/expand/fail/` directories with corresponding Rust source files under test.

### Test actions

The `tryexpand` crate exposes the following functions test actions:

#### cargo expand

The `tryexpand::expand(…)` function runs `cargo expand` for each test file and snapshot the results:

```rust
tryexpand::expand(
// ...
)
.expect_pass();
```

If you wish to also perform additional snapshot tests for all successfully expanded files you can do so via an additional call to either of these:

- `.and_check()` to run `cargo check` for each test file and snapshot the results:

```rust
tryexpand::expand(
// ...
)
.and_check()
.expect_pass();
```

- `.and_run()` to run `cargo run` for each test file and snapshot the results:

```rust
tryexpand::expand(
// ...
)
.and_run()
.expect_pass();
```

- `.and_run_tests()` to run `cargo test` for each test file and snapshot the results:

```rust
tryexpand::expand(
// ...
)
.and_run_tests()
.expect_pass();
```

#### cargo check

The `tryexpand::check(…)` function runs `cargo check` for each test file and snapshot the results:

```rust
tryexpand::check(
// ...
)
.expect_pass();
```

#### cargo run

The `tryexpand::run(…)` function runs `cargo run` for each test file and snapshot the results:

```rust
tryexpand::run(
// ...
)
.expect_pass();
```

#### cargo test

The `tryexpand::run_tests(…)` function runs `cargo test` for each test file and snapshot the results:

```rust
tryexpand::run_tests(
// ...
)
.expect_pass();
```

#### Pass

The base of each `tryexpand` test suite is the `tryexpand::expand()` function, which you pass a list of file paths (or glob patterns) to:
The base of each `tryexpand` test suite is the corresponding [test action](#test-actions) function (we're using `tryexpand::expand()` here, but this applies to all actions), which you pass a list of file paths (or glob patterns) to:

```rust
#[test]
Expand All @@ -50,11 +130,11 @@ pub fn pass() {
}
```

By default `tryexpand::expand()` assert matched test files to expand successfully.
By default `tryexpand`'s [test action](#test-actions) functions assert matched test files to pass their tests.

#### Fail

If instead you want to write tests for macro expansion diagnostics, then will have to add a call to `.expect_fail()`:
If instead you want to write tests for a failure's diagnostics, then ou can do so via an additional call to `.expect_fail()` (we're using `tryexpand::expand(…)` here, but this applies to all actions):

```rust
#[test]
Expand All @@ -67,7 +147,7 @@ pub fn fail() {

#### CLI arguments

Additionally you can specify arguments to pass to `cargo expand`:
Additionally you can specify arguments to pass to the `cargo` command:

```rust
#[test]
Expand All @@ -81,7 +161,7 @@ tryexpand::expand(

#### CLI env vars

as well as environment variables to set for `cargo expand`:
As well as environment variables to set for the `cargo` command:

```rust
tryexpand::expand(
Expand All @@ -92,45 +172,6 @@ tryexpand::expand(
.expect_pass();
```

#### cargo check

You can also make `tryexpand` type-check the expanded code for you (i.e. `cargo check`):

```rust
tryexpand::expand(
// ...
)
// ...
.and_check()
.expect_pass();
```

#### cargo run

Or you can make `tryexpand` run the expanded code for you (i.e. `cargo run`):

```rust
tryexpand::expand(
// ...
)
// ...
.and_run()
.expect_pass();
```

#### cargo test

Or you can make `tryexpand` run the expanded code's included unit tests (if there are any) for you (i.e. `cargo test`):

```rust
tryexpand::expand(
// ...
)
// ...
.and_run_tests()
.expect_pass();
```

### Running tests

The test can be run with:
Expand Down
169 changes: 163 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ pub(crate) const OUT_RS_FILE_SUFFIX: &str = "out.rs";
pub(crate) const OUT_TXT_FILE_SUFFIX: &str = "out.txt";
pub(crate) const ERR_TXT_FILE_SUFFIX: &str = "err.txt";

use crate::test_suite::TestSuite;
use crate::{
test::Action,
test_suite::{BuildTestSuite, ExpandTestSuite, TestSuite},
};

/// Attempts to expand macros in files that match the provided paths/glob patterns.
/// Run snapshot tests on files that match the provided paths/glob patterns,
/// snapshotting the source code as it is produced by `cargo expand`.
///
/// # Examples
///
Expand Down Expand Up @@ -63,18 +67,171 @@ use crate::test_suite::TestSuite;
/// )
/// .args(["--features", "test-feature"])
/// .envs([("MY_ENV", "my env var value")])
/// .and_check() // type-check the expanded code
/// .and_check() // also type-check the code on successful macro-expansion
/// .expect_pass();
/// }
/// ```
#[track_caller] // LOAD-BEARING, DO NOT REMOVE!
pub fn expand<I, P>(patterns: I) -> TestSuite
pub fn expand<I, P>(patterns: I) -> ExpandTestSuite
where
I: IntoIterator<Item = P>,
P: AsRef<Path>,
{
match TestSuite::new(patterns, Location::caller()) {
Ok(test_suite) => test_suite,
match TestSuite::new(patterns, Action::Expand, Location::caller()) {
Ok(test_suite) => ExpandTestSuite(test_suite),
Err(err) => panic!("Error: {err:?}"),
}
}

/// Run snapshot tests on files that match the provided paths/glob patterns,
/// snapshotting the stdout/stderr output as it is produced by `cargo check [ARGS]`.
///
/// # Examples
///
/// Simple:
///
/// ```
/// #[test]
/// pub fn pass() {
/// tryexpand::check(
/// ["tests/expand/pass/*.rs"]
/// ).expect_pass();
/// }
///
/// #[test]
/// pub fn fail() {
/// tryexpand::check(
/// ["tests/expand/fail/*.rs"]
/// ).expect_fail();
/// }
/// ```
///
/// Advanced:
///
/// ```
/// #[test]
/// pub fn pass() {
/// tryexpand::check(
/// [
/// "tests/expand/foo/pass/*.rs",
/// "tests/expand/bar/pass/*.rs"
/// ]
/// )
/// .args(["--features", "test-feature"])
/// .envs([("MY_ENV", "my env var value")])
/// .expect_pass();
/// }
/// ```
#[track_caller] // LOAD-BEARING, DO NOT REMOVE!
pub fn check<I, P>(patterns: I) -> BuildTestSuite
where
I: IntoIterator<Item = P>,
P: AsRef<Path>,
{
match TestSuite::new(patterns, Action::Check, Location::caller()) {
Ok(test_suite) => BuildTestSuite(test_suite),
Err(err) => panic!("Error: {err:?}"),
}
}

/// Run snapshot tests on files that match the provided paths/glob patterns,
/// snapshotting the stdout/stderr output as it is produced by `cargo run [ARGS]`.
///
/// # Examples
///
/// Simple:
///
/// ```
/// #[test]
/// pub fn pass() {
/// tryexpand::run(
/// ["tests/expand/pass/*.rs"]
/// ).expect_pass();
/// }
///
/// #[test]
/// pub fn fail() {
/// tryexpand::run(
/// ["tests/expand/fail/*.rs"]
/// ).expect_fail();
/// }
/// ```
///
/// Advanced:
///
/// ```
/// #[test]
/// pub fn pass() {
/// tryexpand::run(
/// [
/// "tests/expand/foo/pass/*.rs",
/// "tests/expand/bar/pass/*.rs"
/// ]
/// )
/// .args(["--features", "test-feature"])
/// .envs([("MY_ENV", "my env var value")])
/// .expect_pass();
/// }
/// ```
#[track_caller] // LOAD-BEARING, DO NOT REMOVE!
pub fn run<I, P>(patterns: I) -> BuildTestSuite
where
I: IntoIterator<Item = P>,
P: AsRef<Path>,
{
match TestSuite::new(patterns, Action::Run, Location::caller()) {
Ok(test_suite) => BuildTestSuite(test_suite),
Err(err) => panic!("Error: {err:?}"),
}
}

/// Run snapshot tests on files that match the provided paths/glob patterns,
/// snapshotting the stdout/stderr output as it is produced by `cargo test [ARGS]`.
///
/// # Examples
///
/// Simple:
///
/// ```
/// #[test]
/// pub fn pass() {
/// tryexpand::run_tests(
/// ["tests/expand/pass/*.rs"]
/// ).expect_pass();
/// }
///
/// #[test]
/// pub fn fail() {
/// tryexpand::run_tests(
/// ["tests/expand/fail/*.rs"]
/// ).expect_fail();
/// }
/// ```
///
/// Advanced:
///
/// ```
/// #[test]
/// pub fn pass() {
/// tryexpand::run_tests(
/// [
/// "tests/expand/foo/pass/*.rs",
/// "tests/expand/bar/pass/*.rs"
/// ]
/// )
/// .args(["--features", "test-feature"])
/// .envs([("MY_ENV", "my env var value")])
/// .expect_pass();
/// }
/// ```
#[track_caller] // LOAD-BEARING, DO NOT REMOVE!
pub fn run_tests<I, P>(patterns: I) -> BuildTestSuite
where
I: IntoIterator<Item = P>,
P: AsRef<Path>,
{
match TestSuite::new(patterns, Action::Test, Location::caller()) {
Ok(test_suite) => BuildTestSuite(test_suite),
Err(err) => panic!("Error: {err:?}"),
}
}
Loading