Skip to content

Commit

Permalink
Add insta-based snapshot tests that cover side-by-side format
Browse files Browse the repository at this point in the history
I'm going to fix inline diff issue #704, and found that the inline format isn't
covered by CLI tests. I could duplicate compare_all.sh to test various formats,
but it's uneasy to review that a new formatting is better than the previous
version. I think snapshot testing will help guarantee the output quality without
increasing maintenance burden too much.

If we like the idea, maybe we can migrate some of compare_all.sh tests to the
insta-based ones.

Note that this will add ~10sec to "cargo test" runs.
  • Loading branch information
yuja committed Jul 31, 2024
1 parent ab5a7b6 commit 245b464
Show file tree
Hide file tree
Showing 87 changed files with 2,014 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ flamegraph.svg
.idea

sample_files/compare.result
tests/snapshots/*.snap.new

notes.md
9 changes: 9 additions & 0 deletions manual/src/adding_a_parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ $ ./sample_files/compare_all.sh
$ cp sample_files/compare.result sample_files/compare.expected
```

Run the CLI test and [update the snapshots][insta] as well.

```
$ cargo insta test
$ cargo insta accept
```

[insta]: https://insta.rs/docs/quickstart/#reviewing-snapshots

## Maintenance

To update a parser that is already imported, use `git subtree pull`.
Expand Down
43 changes: 43 additions & 0 deletions tests/cli.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::process::Command;
use std::str;

use assert_cmd::prelude::*;
use predicates::prelude::*;
Expand Down Expand Up @@ -269,3 +270,45 @@ fn walk_hidden_items() {
.and(predicate::str::contains("after"));
cmd.assert().stdout(predicate_fn);
}

const MAX_SAMPLE_FILE_SIZE: u64 = 10_000;

#[test]
fn samples_side_by_side() {
insta::glob!("../sample_files", "*_1.*", |left_file| {
let base_dir = left_file.parent().unwrap().parent().unwrap();
let file_name = left_file.file_name().unwrap().to_str().unwrap();
let right_file = left_file.with_file_name(file_name.replace("_1.", "_2."));
// Large sample files are excluded because it's slow to diff with debug
// binary, and the snapshot results wouldn't help review changes.
if left_file.metadata().unwrap().len() > MAX_SAMPLE_FILE_SIZE
|| right_file.metadata().unwrap().len() > MAX_SAMPLE_FILE_SIZE
{
eprintln!("Skipping large sample: {file_name}");
return;
}
// TODO: Fix CI instability on the following architectures:
// x86_64-apple-darwin, x86_64-pc-windows-msvc, aarch64-apple-darwin
if file_name == "f_sharp_1.fs" {
eprintln!("Skipping unstable sample: {file_name}");
return;
}

let to_path_arg = |path: &Path| {
let short_path = path.strip_prefix(base_dir).unwrap();
let short_str = short_path.to_str().unwrap();
short_str.replace(std::path::MAIN_SEPARATOR, "/")
};
let mut cmd = get_base_command();
let assert = cmd
.arg("--color=always")
.arg("--display=side-by-side")
.arg("--width=160")
.arg(to_path_arg(left_file))
.arg(to_path_arg(&right_file))
.assert()
.success();
let stdout = str::from_utf8(&assert.get_output().stdout).unwrap();
insta::assert_snapshot!(stdout);
});
}
32 changes: 32 additions & 0 deletions tests/snapshots/cli__samples_side_by_side@Session_1.kt.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
source: tests/cli.rs
expression: stdout
input_file: sample_files/Session_1.kt
---
sample_files/Session_2.kt --- 1/2 --- Kotlin
 96  /**  96  /**
 97  * The session's photo URL.  97  * The session's photo URL.
 98  */  98  */
 99  val photoUrl: String?,  99  val photoUrl: String,
100  100 
101  /** 101  /**
102  * IDs of the sessions related to this session. 102  * IDs of the sessions related to this session.
sample_files/Session_2.kt --- 2/2 --- Kotlin
114  return startTime <= now && endTime >= now 114  return startTime <= now && endTime >= now
115  } 115  }
...  116 
...  117  val hasPhoto inline get() = photoUrl.isNotEmpty()
116  118 
117  /** 119  /**
118  * Returns whether the session has a video or not. A session could be l 120  * Returns whether the session has a video or not. A session could be l
... ive streaming or have a ... ive streaming or have a
119  * recorded session. Both live stream and recorded videos are stored in 121  * recorded session. Both live stream and recorded videos are stored in
...  [Session.youTubeUrl]. ...  [Session.youTubeUrl].
120  */ 122  */
121  fun hasVideo() = youTubeUrl.isNotEmpty() 123  val hasVideo inline get() = youTubeUrl.isNotEmpty()
...  124 
...  125  val hasPhotoOrVideo inline get() = hasPhoto || hasVideo
122  126 
123  /** 127  /**
124  * The year the session was held. 128  * The year the session was held.
14 changes: 14 additions & 0 deletions tests/snapshots/cli__samples_side_by_side@ada_1.adb.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
source: tests/cli.rs
expression: stdout
input_file: sample_files/ada_1.adb
---
sample_files/ada_2.adb --- Ada
1  with Ada.Text_IO; use Ada.Text_IO; procedure Hello is begin Put_Line ("Hello 1 with Ada.Text_IO;
.  WORLD!"); end Hello; . 
.  2 
.  3 procedure Hello is
.  4  package TIO renames Ada.Text_IO;
.  5 begin
.  6  TIO.Put_Line ("Hello World!");
.  7 end Hello;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
source: tests/cli.rs
expression: stdout
input_file: sample_files/added_line_1.txt
---
sample_files/added_line_2.txt --- Text
1 1 potato
2 2 tomato
 3 legato
10 changes: 10 additions & 0 deletions tests/snapshots/cli__samples_side_by_side@align_footer_1.txt.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
source: tests/cli.rs
expression: stdout
input_file: sample_files/align_footer_1.txt
---
sample_files/align_footer_2.txt --- Text
1 before 1 before
2  foo x 2  x
3 y . 
4 after 3 after
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: tests/cli.rs
expression: stdout
input_file: sample_files/all_changed_1.js
---
sample_files/all_changed_2.js --- JavaScript
1 a 1 b
7 changes: 7 additions & 0 deletions tests/snapshots/cli__samples_side_by_side@apex_1.cls.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: tests/cli.rs
expression: stdout
input_file: sample_files/apex_1.cls
---
sample_files/apex_2.cls --- Apex
No syntactic changes.
33 changes: 33 additions & 0 deletions tests/snapshots/cli__samples_side_by_side@bad_combine_1.rs.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
source: tests/cli.rs
expression: stdout
input_file: sample_files/bad_combine_1.rs
---
sample_files/bad_combine_2.rs --- 1/2 --- Rust
 1  . 
 2 fn column_widths( . 
 3  hunks: &[Hunk], . 
 4  lhs_mps: &[MatchedPos], . 
 5  rhs_mps: &[MatchedPos], . 
 6  max_lhs_src_line: LineNumber, . 
 7  max_rhs_src_line: LineNumber, . 
 8 ) { . 
 9 } . 
10  . 
11 fn display_line_nums( 1 fn display_line_nums(
12 ) -> (String, String) { 2 ) -> (String, String) {
13  let display_rhs_line_num: String = match rhs_line_num { 3  let display_rhs_line_num: String = match rhs_line_num {
14  Some(line_num) => { 4  Some(line_num) => {
15  let s = format_line_num_padded(line_num, rhs_column_width); 5  let s = format_line_num_padded(line_num, widths.rhs_line_nums);
16  if rhs_lines_with_novel.contains(&line_num) { 6  if rhs_lines_with_novel.contains(&line_num) {
17  s.bright_green().to_string() 7  s.bright_green().to_string()
18  } else { 8  } else {

sample_files/bad_combine_2.rs --- 2/2 --- Rust
21  } 11  }
22  None => format_missing_line_num( 12  None => format_missing_line_num(
23  prev_rhs_line_num.unwrap_or_else(|| 10.into()), 13  prev_rhs_line_num.unwrap_or_else(|| 10.into()),
24  rhs_column_width, 14  widths.rhs_line_nums,
25  ), 15  ),
26  }; 16  };
27  17 
51 changes: 51 additions & 0 deletions tests/snapshots/cli__samples_side_by_side@big_text_hunk_1.txt.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
source: tests/cli.rs
expression: stdout
input_file: sample_files/big_text_hunk_1.txt
---
sample_files/big_text_hunk_2.txt --- Text
5  5 github.com/naoina/toml v0.1.1/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
6  6 github.com/streadway/amqp v0.0.0-20160311215503-2e25825abdbd h1:625/bJvSNfQrzzK5ttnUqMqnVe8M5MILmf5ZRGgeeDY=
7  7 github.com/streadway/amqp v0.0.0-20160311215503-2e25825abdbd/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY=
  8 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
  9 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 10 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 11 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 12 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 13 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 14 go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
 15 go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
 16 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 17 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 18 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 19 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 20 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 21 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 22 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 23 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 24 golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 25 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 26 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 27 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 28 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 29 golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 30 golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
 31 golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
 32 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 33 golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
 34 golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
 35 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 36 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 37 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 38 golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
 39 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 40 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 41 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 42 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 43 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 44 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 45 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 46 golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
 47 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 48 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 49 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
source: tests/cli.rs
expression: stdout
input_file: sample_files/change_outer_1.el
---
sample_files/change_outer_2.el --- Emacs Lisp
1 (lhs comma rhs) 1 [(lhs) comma rhs]
Loading

0 comments on commit 245b464

Please sign in to comment.