Skip to content

Commit c35007d

Browse files
committed
Auto merge of rust-lang#75773 - matklad:snapshot-tests, r=Mark-Simulacrum
Introduce expect snapshot testing library into rustc Snapshot testing is a technique for writing maintainable unit tests. Unlike usual `assert_eq!` tests, snapshot tests allow to *automatically* upgrade expected values on test failure. In a sense, snapshot tests are inline-version of our beloved UI-tests. Example: ![expect](https://user-images.githubusercontent.com/1711539/90888810-3bcc8180-e3b7-11ea-9626-d06e89e1a0bb.gif) A particular library we use, `expect_test` provides an `expect!` macro, which creates a sort of self-updating string literal (by using `file!` macro). Self-update is triggered by setting `UPDATE_EXPECT` environmental variable (this info is printed during the test failure). This library was extracted from rust-analyzer, where we use it for most of our tests. There are some other, more popular snapshot testing libraries: * https://github.com/mitsuhiko/insta * https://github.com/aaronabramov/k9 The main differences of `expect` are: * first-class snapshot objects (so, tests can be written as functions, rather than as macros) * focus on inline-snapshots (but file snapshots are also supported) * restricted feature set (only `assert_eq` and `assert_debug_eq`) * no extra runtime (ie, no `cargo insta`) See rust-lang/rust-analyzer#5101 for a an extended comparison. It is unclear if this testing style will stick with rustc in the long run. At the moment, rustc is mainly tested via integrated UI tests. But in the library-ified world, unit-tests will become somewhat more important (that's why use use `rustc_lexer` library-ified library as an example in this PR). Given that the cost of removal shouldn't be too high, it probably makes sense to just see if this flies!
2 parents 3d6a3ed + f7be59c commit c35007d

File tree

6 files changed

+67
-0
lines changed

6 files changed

+67
-0
lines changed

Cargo.lock

+11
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,16 @@ dependencies = [
10081008
"yaml-rust 0.4.4",
10091009
]
10101010

1011+
[[package]]
1012+
name = "expect-test"
1013+
version = "0.1.0"
1014+
source = "registry+https://github.com/rust-lang/crates.io-index"
1015+
checksum = "a3e383741ea1982866572109d1a8c807bd36aad91fca701489fdca56ef92b3b8"
1016+
dependencies = [
1017+
"difference",
1018+
"once_cell",
1019+
]
1020+
10111021
[[package]]
10121022
name = "failure"
10131023
version = "0.1.8"
@@ -3653,6 +3663,7 @@ dependencies = [
36533663
name = "rustc_lexer"
36543664
version = "0.1.0"
36553665
dependencies = [
3666+
"expect-test",
36563667
"unicode-xid",
36573668
]
36583669

src/bootstrap/test.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1754,6 +1754,11 @@ impl Step for Crate {
17541754
cargo.arg("--quiet");
17551755
}
17561756

1757+
if builder.config.cmd.bless() {
1758+
// Bless `expect!` tests.
1759+
cargo.env("UPDATE_EXPECT", "1");
1760+
}
1761+
17571762
if target.contains("emscripten") {
17581763
cargo.env(
17591764
format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),

src/librustc_lexer/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,6 @@ name = "rustc_lexer"
1919
# Note that this crate purposefully does not depend on other rustc crates
2020
[dependencies]
2121
unicode-xid = "0.2.0"
22+
23+
[dev-dependencies]
24+
expect-test = "0.1"

src/librustc_lexer/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use std::convert::TryFrom;
3535
/// Parsed token.
3636
/// It doesn't contain information about data that has been parsed,
3737
/// only the type of the token and its size.
38+
#[derive(Debug)]
3839
pub struct Token {
3940
pub kind: TokenKind,
4041
pub len: usize,

src/librustc_lexer/src/tests.rs

+45
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use super::*;
22

3+
use expect_test::{expect, Expect};
4+
35
fn check_raw_str(s: &str, expected_hashes: u16, expected_err: Option<RawStrError>) {
46
let s = &format!("r{}", s);
57
let mut cursor = Cursor::new(s);
@@ -120,3 +122,46 @@ fn test_shebang_followed_by_attrib() {
120122
let input = "#!/bin/rust-scripts\n#![allow_unused(true)]";
121123
assert_eq!(strip_shebang(input), Some(19));
122124
}
125+
126+
fn check_lexing(src: &str, expect: Expect) {
127+
let actual: String = tokenize(src).map(|token| format!("{:?}\n", token)).collect();
128+
expect.assert_eq(&actual)
129+
}
130+
131+
#[test]
132+
fn comment_flavors() {
133+
check_lexing(
134+
r"
135+
// line
136+
//// line as well
137+
/// outer doc line
138+
//! inner doc line
139+
/* block */
140+
/**/
141+
/*** also block */
142+
/** outer doc block */
143+
/*! inner doc block */
144+
",
145+
expect![[r#"
146+
Token { kind: Whitespace, len: 1 }
147+
Token { kind: LineComment { doc_style: None }, len: 7 }
148+
Token { kind: Whitespace, len: 1 }
149+
Token { kind: LineComment { doc_style: None }, len: 17 }
150+
Token { kind: Whitespace, len: 1 }
151+
Token { kind: LineComment { doc_style: Some(Outer) }, len: 18 }
152+
Token { kind: Whitespace, len: 1 }
153+
Token { kind: LineComment { doc_style: Some(Inner) }, len: 18 }
154+
Token { kind: Whitespace, len: 1 }
155+
Token { kind: BlockComment { doc_style: None, terminated: true }, len: 11 }
156+
Token { kind: Whitespace, len: 1 }
157+
Token { kind: BlockComment { doc_style: None, terminated: true }, len: 4 }
158+
Token { kind: Whitespace, len: 1 }
159+
Token { kind: BlockComment { doc_style: None, terminated: true }, len: 18 }
160+
Token { kind: Whitespace, len: 1 }
161+
Token { kind: BlockComment { doc_style: Some(Outer), terminated: true }, len: 22 }
162+
Token { kind: Whitespace, len: 1 }
163+
Token { kind: BlockComment { doc_style: Some(Inner), terminated: true }, len: 22 }
164+
Token { kind: Whitespace, len: 1 }
165+
"#]],
166+
)
167+
}

src/tools/tidy/src/deps.rs

+2
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ const PERMITTED_DEPENDENCIES: &[&str] = &[
8585
"crossbeam-queue",
8686
"crossbeam-utils",
8787
"datafrog",
88+
"difference",
8889
"digest",
8990
"dlmalloc",
9091
"either",
9192
"ena",
9293
"env_logger",
94+
"expect-test",
9395
"fake-simd",
9496
"filetime",
9597
"flate2",

0 commit comments

Comments
 (0)