Skip to content

Commit 9f021ea

Browse files
authored
test(stackable-versioned): Combine snapshot and compile tests (#1041)
* test(stackable-versioned): Move snapshot tests * test(stackable-versioned): Move ui/compile tests * test(stackable-versioned): Combine snapshot and compile tests * chore(stackable-versioned): Update testing README
1 parent d990019 commit 9f021ea

File tree

72 files changed

+400
-159
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+400
-159
lines changed

crates/stackable-versioned-macros/fixtures/README.md

Lines changed: 0 additions & 62 deletions
This file was deleted.

crates/stackable-versioned-macros/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -922,16 +922,16 @@ where
922922
}
923923

924924
#[cfg(test)]
925-
mod test {
925+
mod snapshot_tests {
926926
use insta::{assert_snapshot, glob};
927927

928928
use super::*;
929929

930930
#[test]
931-
fn default_snapshots() {
931+
fn default() {
932932
let _settings_guard = test_utils::set_snapshot_path().bind_to_scope();
933933

934-
glob!("../fixtures/inputs/default", "*.rs", |path| {
934+
glob!("../tests/inputs/default/pass", "*.rs", |path| {
935935
let formatted = test_utils::expand_from_file(path)
936936
.inspect_err(|err| eprintln!("{err}"))
937937
.unwrap();
@@ -941,10 +941,10 @@ mod test {
941941

942942
#[cfg(feature = "k8s")]
943943
#[test]
944-
fn k8s_snapshots() {
944+
fn k8s() {
945945
let _settings_guard = test_utils::set_snapshot_path().bind_to_scope();
946946

947-
glob!("../fixtures/inputs/k8s", "*.rs", |path| {
947+
glob!("../tests/inputs/k8s/pass", "*.rs", |path| {
948948
let formatted = test_utils::expand_from_file(path)
949949
.inspect_err(|err| eprintln!("{err}"))
950950
.unwrap();

crates/stackable-versioned-macros/src/test_utils.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77
use insta::Settings;
88
use proc_macro2::TokenStream;
99
use regex::Regex;
10-
use snafu::{OptionExt, ResultExt, Snafu};
10+
use snafu::{NoneError, OptionExt, ResultExt, Snafu};
1111
use syn::Item;
1212

1313
use crate::versioned_impl;
@@ -24,8 +24,8 @@ pub(crate) enum Error {
2424
#[snafu(display("failed to read input file"))]
2525
ReadFile { source: std::io::Error },
2626

27-
#[snafu(display("failed to find delimiter"))]
28-
MissingDelimiter,
27+
#[snafu(display("failed to find delimiters"))]
28+
MissingDelimiters,
2929

3030
#[snafu(display("failed to find regex match group"))]
3131
MissingRegexMatchGroup,
@@ -51,7 +51,13 @@ pub(crate) fn expand_from_file(path: &Path) -> Result<String, Error> {
5151
}
5252

5353
fn prepare_from_string(input: String) -> Result<(TokenStream, Item), Error> {
54-
let (attrs, input) = input.split_once(DELIMITER).context(MissingDelimiterSnafu)?;
54+
let parts: [&str; 4] = input
55+
.split(DELIMITER)
56+
.collect::<Vec<_>>()
57+
.try_into()
58+
.map_err(|_| NoneError)
59+
.context(MissingDelimitersSnafu)?;
60+
let [_, attrs, input, _] = parts;
5561

5662
let attrs = REGEX
5763
.captures(attrs)
@@ -70,7 +76,7 @@ fn prepare_from_string(input: String) -> Result<(TokenStream, Item), Error> {
7076
pub(crate) fn set_snapshot_path() -> Settings {
7177
let dir = std::env::var("CARGO_MANIFEST_DIR").expect("env var CARGO_MANIFEST_DIR must be set");
7278
let mut settings = Settings::clone_current();
73-
settings.set_snapshot_path(PathBuf::from(dir).join("fixtures/snapshots"));
79+
settings.set_snapshot_path(PathBuf::from(dir).join("tests/snapshots"));
7480

7581
settings
7682
}
Lines changed: 87 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,97 @@
1-
# Compile-Fail Testing
1+
# Testing the `#[versioned]` macro
22

3-
> [!NOTE]
4-
> Also see the snapshot tests, described [here](../fixtures/README.md).
5-
6-
This type of testing is part of UI testing. These tests assert two things: First, the code should
7-
**not** compile and secondly should also produce the expected rustc (compiler) error message. For
8-
this type of testing, we use the [`trybuild`][trybuild] crate.
3+
This folder contains both snapshot and compile (trybuild) tests. Both types of tests use the same
4+
set of input files to both ensure the macro generates the expected code and either compiles or
5+
produces the expected compile error.
96

107
Tests are currently separated into two folders: `default` and `k8s`. The default test cases don't
118
require any additional features to be activated. The Kubernetes specific tests require the `k8s`
129
feature to be enabled. These tests can be run with `cargo test --all-features`.
1310

11+
## Snapshot Testing
12+
13+
> [!NOTE]
14+
> Please have `rust-src` installed, e.g. using `rustup component add rust-src`.
15+
>
16+
> Also see the compile-fail tests, described [here](#compile-fail-testing).
17+
18+
Snapshot testing is done using the [insta] crate. It provides a [CLI tool][insta-cli] calle
19+
`cargo-insta` and a [VS Code extension][insta-ext].
20+
21+
Test inputs and snapshots of the expected output are located in the `inputs` and `snapshots` folder
22+
respectively. Each Rust attribute macro expects two inputs as a token stream:
23+
24+
> The first TokenStream is the delimited token tree following the attribute’s name, not including
25+
> the outer delimiters. If the attribute is written as a bare attribute name, the attribute
26+
> TokenStream is empty. The second TokenStream is the rest of the item including other attributes on
27+
> the item.
28+
>
29+
> _(Taken from the [Rust reference][rust-ref])_
30+
31+
Because of that, a special delimiter is used in the input files which separates different sections
32+
of the input file while still enabling developers to write valid Rust code. The delimiter is
33+
`// ---\n`. Most of the inner workings are located in [this file](../src/test_utils.rs).
34+
35+
```rust
36+
use stackable_versioned::versioned;
37+
// --- <- See here!
38+
#[versioned(
39+
version(name = "v1alpha1"),
40+
version(name = "v1beta1"),
41+
version(name = "v1")
42+
)]
43+
// --- <- See here!
44+
pub(crate) struct Foo {
45+
#[versioned(
46+
changed(since = "v1beta1", from_name = "jjj", from_type = "u8"),
47+
changed(since = "v1", from_type = "u16"),
48+
)]
49+
bar: usize,
50+
baz: bool,
51+
}
52+
// --- <- See here!
53+
fn main() {}
54+
55+
// Rest of code ...
56+
```
57+
58+
Input files must include **three** separators which produce **four** distinct sections:
59+
60+
- Imports, like `stackable_versioned::versioned`
61+
- The attribute macro
62+
- The item the macro is applied to
63+
- The rest of the code, like the `main` function
64+
65+
### Recommended Workflow
66+
67+
First, add new input files (which automatically get picked up by `insta`) to the `inputs`
68+
folder. Make sure the delimiter is placed correctly between the different sections. Doc comments on
69+
the container have to be placed after the delimiter. Next, generate the snapshot files (initially
70+
not accepted) by running
71+
72+
```shell
73+
cargo insta test -p stackable-versioned-macros --all-features
74+
```
75+
76+
This command will place the new snapshot files (with a `.new` extension) in the `snapshots` folder.
77+
These new snapshot files must not appear on `main`, but can be shared on branches for collaboration.
78+
To review them, run the `cargo insta review` command, then accept or fix the snapshots. Once all are
79+
accepted (ie: no `.new` files remaining), check in the files.
80+
81+
## Compile-Fail Testing
82+
83+
> [!NOTE]
84+
> Also see the snapshot tests, described [here](#snapshot-testing).
85+
86+
This type of testing is part of UI testing. These tests assert two things: First, some code should
87+
compile without errors and secondly other code should produce the expected rustc (compiler) error
88+
message. For this type of testing, we use the [`trybuild`][trybuild] crate.
89+
1490
Further information about the workflow are described [here][workflow].
1591

92+
[rust-ref]: https://doc.rust-lang.org/reference/procedural-macros.html#attribute-macros
1693
[workflow]: https://docs.rs/trybuild/latest/trybuild/#workflow
1794
[trybuild]: https://docs.rs/trybuild/latest/trybuild/
95+
[insta-ext]: https://insta.rs/docs/vscode/
96+
[insta-cli]: https://insta.rs/docs/cli/
97+
[insta]: https://insta.rs/

crates/stackable-versioned-macros/tests/default/pass/added.rs

Lines changed: 0 additions & 23 deletions
This file was deleted.

crates/stackable-versioned-macros/tests/default/fail/changed.stderr renamed to crates/stackable-versioned-macros/tests/inputs/default/fail/changed.stderr

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/stackable-versioned-macros/tests/default/fail/deprecate.stderr renamed to crates/stackable-versioned-macros/tests/inputs/default/fail/deprecate.stderr

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/stackable-versioned-macros/tests/default/fail/skip_from_all.stderr renamed to crates/stackable-versioned-macros/tests/inputs/default/fail/skip_from_all.stderr

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/stackable-versioned-macros/tests/default/fail/skip_from_version.stderr renamed to crates/stackable-versioned-macros/tests/inputs/default/fail/skip_from_version.stderr

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/stackable-versioned-macros/tests/default/fail/submodule_invalid_name.stderr renamed to crates/stackable-versioned-macros/tests/inputs/default/fail/submodule_invalid_name.stderr

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/stackable-versioned-macros/tests/default/fail/submodule_use_statement.stderr renamed to crates/stackable-versioned-macros/tests/inputs/default/fail/submodule_use_statement.stderr

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use stackable_versioned_macros::versioned;
2+
// ---
3+
#[versioned(
4+
version(name = "v1alpha1"),
5+
version(name = "v1alpha2"),
6+
version(name = "v1beta1"),
7+
version(name = "v1")
8+
)]
9+
// ---
10+
struct Foo {
11+
username: String,
12+
13+
#[versioned(added(since = "v1alpha2", default = default_first_name))]
14+
first_name: String,
15+
16+
#[versioned(added(since = "v1beta1"))]
17+
last_name: String,
18+
}
19+
// ---
20+
fn main() {}
21+
22+
fn default_first_name() -> String {
23+
"foo".into()
24+
}

crates/stackable-versioned-macros/fixtures/inputs/default/attribute_enum.rs renamed to crates/stackable-versioned-macros/tests/inputs/default/pass/attribute_enum.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use stackable_versioned::versioned;
2+
// ---
13
#[versioned(
24
version(name = "v1alpha1"),
35
version(
@@ -36,3 +38,5 @@ enum Foo {
3638
#[versioned(changed(since = "v1", from_name = "Qaax"))]
3739
Quux,
3840
}
41+
// ---
42+
fn main() {}

0 commit comments

Comments
 (0)