Skip to content

Commit 45ac232

Browse files
committed
test: Use indoc to improve string formatting
- allows testing stdout explicitly - makes doc blocks more readable
1 parent 44f1324 commit 45ac232

File tree

4 files changed

+126
-125
lines changed

4 files changed

+126
-125
lines changed

src/common_test.rs

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ pub mod tests {
66
path::PathBuf,
77
};
88

9+
use indoc::indoc;
10+
911
use tempfile::tempdir;
1012

1113
use crate::{ownership::Ownership, project::Project};
@@ -21,18 +23,18 @@ pub mod tests {
2123
}};
2224
}
2325

24-
const DEFAULT_CODE_OWNERSHIP_YML: &str = "
25-
---
26-
owned_globs:
27-
- \"{app,components,config,frontend,lib,packs,spec}/**/*.{rb,rake,js,jsx,ts,tsx,json,yml}\"
28-
unowned_globs:
29-
- config/code_ownership.yml
30-
javascript_package_paths:
31-
- javascript/packages/**
32-
vendored_gems_path: gems
33-
team_file_glob:
34-
- config/teams/**/*.yml
35-
";
26+
const DEFAULT_CODE_OWNERSHIP_YML: &str = indoc! {"
27+
---
28+
owned_globs:
29+
- \"{app,components,config,frontend,lib,packs,spec}/**/*.{rb,rake,js,jsx,ts,tsx,json,yml}\"
30+
unowned_globs:
31+
- config/code_ownership.yml
32+
javascript_package_paths:
33+
- javascript/packages/**
34+
vendored_gems_path: gems
35+
team_file_glob:
36+
- config/teams/**/*.yml
37+
"};
3638

3739
#[derive(Debug)]
3840
pub struct TestConfig {

src/ownership.rs

Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ fn parse_for_team(team_name: String, codeowners_file: &str) -> Result<Vec<TeamOw
206206
mod tests {
207207
use super::*;
208208
use crate::common_test::tests::{build_ownership_with_all_mappers, vecs_match};
209+
use indoc::indoc;
209210

210211
#[test]
211212
fn test_for_file_owner() -> Result<(), Box<dyn Error>> {
@@ -243,17 +244,17 @@ mod tests {
243244

244245
#[test]
245246
fn test_parse_for_team_trims_header() -> Result<(), Box<dyn Error>> {
246-
let codeownership_file = r#"
247-
# STOP! - DO NOT EDIT THIS FILE MANUALLY
248-
# This file was automatically generated by "bin/codeownership validate".
249-
#
250-
# CODEOWNERS is used for GitHub to suggest code/file owners to various GitHub
251-
# teams. This is useful when developers create Pull Requests since the
252-
# code/file owner is notified. Reference GitHub docs for more details:
253-
# https://help.github.com/en/articles/about-code-owners
247+
let codeownership_file = indoc! {"
248+
# STOP! - DO NOT EDIT THIS FILE MANUALLY
249+
# This file was automatically generated by \"bin/codeownership validate\".
250+
#
251+
# CODEOWNERS is used for GitHub to suggest code/file owners to various GitHub
252+
# teams. This is useful when developers create Pull Requests since the
253+
# code/file owner is notified. Reference GitHub docs for more details:
254+
# https://help.github.com/en/articles/about-code-owners
254255
255256
256-
"#;
257+
"};
257258

258259
let team_ownership = parse_for_team("@Bar".to_string(), codeownership_file)?;
259260
assert!(team_ownership.is_empty());
@@ -262,14 +263,14 @@ mod tests {
262263

263264
#[test]
264265
fn test_parse_for_team_includes_owned_globs() -> Result<(), Box<dyn Error>> {
265-
let codeownership_file = r#"
266-
# First Section
267-
/path/to/owned @Foo
268-
/path/to/not/owned @Bar
266+
let codeownership_file = indoc! {"
267+
# First Section
268+
/path/to/owned @Foo
269+
/path/to/not/owned @Bar
269270
270-
# Last Section
271-
/another/owned/path @Foo
272-
"#;
271+
# Last Section
272+
/another/owned/path @Foo
273+
"};
273274

274275
let team_ownership = parse_for_team("@Foo".to_string(), codeownership_file)?;
275276
vecs_match(
@@ -290,11 +291,11 @@ mod tests {
290291

291292
#[test]
292293
fn test_parse_for_team_with_partial_team_match() -> Result<(), Box<dyn Error>> {
293-
let codeownership_file = r#"
294-
# First Section
295-
/path/to/owned @Foo
296-
/path/to/not/owned @FooBar
297-
"#;
294+
let codeownership_file = indoc! {"
295+
# First Section
296+
/path/to/owned @Foo
297+
/path/to/not/owned @FooBar
298+
"};
298299

299300
let team_ownership = parse_for_team("@Foo".to_string(), codeownership_file)?;
300301
vecs_match(
@@ -309,16 +310,16 @@ mod tests {
309310

310311
#[test]
311312
fn test_parse_for_team_with_trailing_newlines() -> Result<(), Box<dyn Error>> {
312-
let codeownership_file = r#"
313-
# First Section
314-
/path/to/owned @Foo
313+
let codeownership_file = indoc! {"
314+
# First Section
315+
/path/to/owned @Foo
315316
316-
# Last Section
317-
/another/owned/path @Foo
317+
# Last Section
318+
/another/owned/path @Foo
318319
319320
320321
321-
"#;
322+
"};
322323

323324
let team_ownership = parse_for_team("@Foo".to_string(), codeownership_file)?;
324325
vecs_match(
@@ -339,9 +340,9 @@ mod tests {
339340

340341
#[test]
341342
fn test_parse_for_team_without_trailing_newline() -> Result<(), Box<dyn Error>> {
342-
let codeownership_file = r#"
343-
# First Section
344-
/path/to/owned @Foo"#;
343+
let codeownership_file = indoc! {"
344+
# First Section
345+
/path/to/owned @Foo"};
345346

346347
let team_ownership = parse_for_team("@Foo".to_string(), codeownership_file)?;
347348
vecs_match(
@@ -356,12 +357,12 @@ mod tests {
356357

357358
#[test]
358359
fn test_parse_for_team_with_missing_section_header() -> Result<(), Box<dyn Error>> {
359-
let codeownership_file = r#"
360-
# First Section
361-
/path/to/owned @Foo
360+
let codeownership_file = indoc! {"
361+
# First Section
362+
/path/to/owned @Foo
362363
363-
/another/owned/path @Foo
364-
"#;
364+
/another/owned/path @Foo
365+
"};
365366

366367
let team_ownership = parse_for_team("@Foo".to_string(), codeownership_file);
367368
assert!(team_ownership
@@ -371,10 +372,10 @@ mod tests {
371372

372373
#[test]
373374
fn test_parse_for_team_with_malformed_team_line() -> Result<(), Box<dyn Error>> {
374-
let codeownership_file = r#"
375-
# First Section
376-
@Foo
377-
"#;
375+
let codeownership_file = indoc! {"
376+
# First Section
377+
@Foo
378+
"};
378379

379380
let team_ownership = parse_for_team("@Foo".to_string(), codeownership_file);
380381
assert!(team_ownership
@@ -384,11 +385,11 @@ mod tests {
384385

385386
#[test]
386387
fn test_parse_for_team_with_invalid_file() -> Result<(), Box<dyn Error>> {
387-
let codeownership_file = r#"
388-
# First Section
389-
# Second Section
390-
path/to/owned @Foo
391-
"#;
388+
let codeownership_file = indoc! {"
389+
# First Section
390+
# Second Section
391+
path/to/owned @Foo
392+
"};
392393
let team_ownership = parse_for_team("@Foo".to_string(), codeownership_file)?;
393394
vecs_match(
394395
&team_ownership,

tests/invalid_project_test.rs

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use assert_cmd::prelude::*;
2+
use indoc::indoc;
23
use predicates::prelude::*;
34
use std::{error::Error, process::Command};
45

@@ -10,31 +11,24 @@ fn test_validate() -> Result<(), Box<dyn Error>> {
1011
.arg("validate")
1112
.assert()
1213
.failure()
13-
.stdout(predicate::str::contains(
14-
"CODEOWNERS out of date. Run `codeowners generate` to update the CODEOWNERS file",
15-
))
16-
.stdout(predicate::str::contains(
17-
"Some files are missing ownership\n- ruby/app/models/blockchain.rb\n- ruby/app/unowned.rb",
18-
))
19-
.stdout(predicate::str::contains(
20-
"Found invalid team annotations\n- ruby/app/models/blockchain.rb is referencing an invalid team - 'Web3'",
21-
))
22-
.stdout(predicate::str::contains(
23-
"Code ownership should only be defined for each file in one way. The following files have declared ownership in multiple ways",
24-
))
25-
.stdout(predicate::str::contains(
26-
"gems/payroll_calculator/calculator.rb (owner: Payments, source: Owner annotation at the top of the file)",
27-
))
28-
.stdout(predicate::str::contains(
29-
"gems/payroll_calculator/calculator.rb (owner: Payroll, source: Owner specified in Team YML's `owned_gems`)",
30-
))
31-
.stdout(predicate::str::contains(
32-
"ruby/app/services/multi_owned.rb (owner: Payments, source: Owner annotation at the top of the file)",
33-
))
34-
.stdout(predicate::str::contains(
35-
"ruby/app/services/multi_owned.rb (owner: Payroll, source: Owner specified in `ruby/app/services/.codeowner`",
36-
));
14+
.stdout(predicate::eq(indoc! {"
3715
16+
CODEOWNERS out of date. Run `codeowners generate` to update the CODEOWNERS file
17+
18+
Code ownership should only be defined for each file in one way. The following files have declared ownership in multiple ways
19+
- gems/payroll_calculator/calculator.rb (owner: Payments, source: Owner annotation at the top of the file)
20+
- gems/payroll_calculator/calculator.rb (owner: Payroll, source: Owner specified in Team YML's `owned_gems`)
21+
- ruby/app/services/multi_owned.rb (owner: Payments, source: Owner annotation at the top of the file)
22+
- ruby/app/services/multi_owned.rb (owner: Payroll, source: Owner specified in `ruby/app/services/.codeowner`)
23+
24+
Found invalid team annotations
25+
- ruby/app/models/blockchain.rb is referencing an invalid team - 'Web3'
26+
27+
Some files are missing ownership
28+
- ruby/app/models/blockchain.rb
29+
- ruby/app/unowned.rb
30+
31+
"}));
3832
Ok(())
3933
}
4034

@@ -47,9 +41,10 @@ fn test_for_file() -> Result<(), Box<dyn Error>> {
4741
.arg("ruby/app/models/blockchain.rb")
4842
.assert()
4943
.success()
50-
.stdout(predicate::str::contains("Team: Unowned"))
51-
.stdout(predicate::str::contains("Team YML: Unowned"));
52-
44+
.stdout(predicate::eq(indoc! {"
45+
Team: Unowned
46+
Team YML: Unowned
47+
Description: \n"})); // trailing whitespace
5348
Ok(())
5449
}
5550

@@ -62,15 +57,17 @@ fn test_for_file_multiple_owners() -> Result<(), Box<dyn Error>> {
6257
.arg("ruby/app/services/multi_owned.rb")
6358
.assert()
6459
.success()
65-
.stdout(predicate::str::contains("Error: file is owned by multiple teams!"))
66-
.stdout(predicate::str::contains("Team: Payments"))
67-
.stdout(predicate::str::contains("Team YML: config/teams/payments.yml"))
68-
.stdout(predicate::str::contains("Description: Owner annotation at the top of the file"))
69-
.stdout(predicate::str::contains("Team: Payroll"))
70-
.stdout(predicate::str::contains("Team YML: config/teams/payroll.yml"))
71-
.stdout(predicate::str::contains(
72-
"Description: Owner specified in `ruby/app/services/.codeowner`",
73-
));
74-
60+
.stdout(predicate::str::starts_with("Error: file is owned by multiple teams!"))
61+
// order not static
62+
.stdout(predicate::str::contains(indoc! {"
63+
Team: Payroll
64+
Team YML: config/teams/payroll.yml
65+
Description: Owner specified in `ruby/app/services/.codeowner`
66+
"}))
67+
.stdout(predicate::str::contains(indoc! {"
68+
Team: Payments
69+
Team YML: config/teams/payments.yml
70+
Description: Owner annotation at the top of the file
71+
"}));
7572
Ok(())
7673
}

tests/valid_project_test.rs

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use assert_cmd::prelude::*;
2+
use indoc::indoc;
23
use predicates::prelude::predicate;
34
use std::{error::Error, path::Path, process::Command};
45

@@ -42,50 +43,48 @@ fn test_for_file() -> Result<(), Box<dyn Error>> {
4243
.arg("ruby/app/models/payroll.rb")
4344
.assert()
4445
.success()
45-
.stdout(predicate::str::contains("Team: Payroll"))
46-
.stdout(predicate::str::contains("Team YML: config/teams/payroll.yml"));
47-
46+
.stdout(predicate::eq(indoc! {"
47+
Team: Payroll
48+
Team YML: config/teams/payroll.yml
49+
Description: Owner annotation at the top of the file
50+
"}));
4851
Ok(())
4952
}
5053

5154
#[test]
5255
fn test_for_team() -> Result<(), Box<dyn Error>> {
53-
let expected_stdout = r#"
54-
# Code Ownership Report for `Payroll` Team
55-
56-
## Annotations at the top of file
57-
/javascript/packages/PayrollFlow/index.tsx
58-
/ruby/app/models/payroll.rb
59-
60-
## Team-specific owned globs
61-
This team owns nothing in this category.
62-
63-
## Owner in .codeowner
64-
/ruby/app/payroll/**/**
65-
66-
## Owner metadata key in package.yml
67-
/ruby/packages/payroll_flow/**/**
68-
69-
## Owner metadata key in package.json
70-
/javascript/packages/PayrollFlow/**/**
71-
72-
## Team YML ownership
73-
/config/teams/payroll.yml
74-
75-
## Team owned gems
76-
/gems/payroll_calculator/**/**
77-
"#
78-
.trim_start();
79-
8056
Command::cargo_bin("codeowners")?
8157
.arg("--project-root")
8258
.arg("tests/fixtures/valid_project")
8359
.arg("for-team")
8460
.arg("Payroll")
8561
.assert()
8662
.success()
87-
.stdout(predicate::eq(expected_stdout));
63+
.stdout(predicate::eq(indoc! {"
64+
# Code Ownership Report for `Payroll` Team
65+
66+
## Annotations at the top of file
67+
/javascript/packages/PayrollFlow/index.tsx
68+
/ruby/app/models/payroll.rb
69+
70+
## Team-specific owned globs
71+
This team owns nothing in this category.
72+
73+
## Owner in .codeowner
74+
/ruby/app/payroll/**/**
75+
76+
## Owner metadata key in package.yml
77+
/ruby/packages/payroll_flow/**/**
78+
79+
## Owner metadata key in package.json
80+
/javascript/packages/PayrollFlow/**/**
81+
82+
## Team YML ownership
83+
/config/teams/payroll.yml
8884
85+
## Team owned gems
86+
/gems/payroll_calculator/**/**
87+
"}));
8988
Ok(())
9089
}
9190

@@ -98,7 +97,9 @@ fn test_for_missing_team() -> Result<(), Box<dyn Error>> {
9897
.arg("Nope")
9998
.assert()
10099
.success()
101-
.stdout(predicate::str::contains("Team not found"));
100+
.stdout(predicate::eq(indoc! {"
101+
Team not found
102+
"}));
102103

103104
Ok(())
104105
}

0 commit comments

Comments
 (0)