Skip to content

Commit

Permalink
switched from manual to semi-automated snapshot tests (#1327)
Browse files Browse the repository at this point in the history
* switched to insta for better snapshot testing
  • Loading branch information
CommanderStorm authored Jul 20, 2024
1 parent 28bb3ad commit 9d1b65e
Show file tree
Hide file tree
Showing 95 changed files with 4,974 additions and 454 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/server-cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ jobs:
run: |
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
- run: cargo test --workspace
- name: Setup | install insta
run: curl -LsSf https://insta.rs/install.sh | sh
- run: cargo insta test --workspace
working-directory: server
linting:
runs-on: ubuntu-latest
Expand Down
1 change: 0 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ data/sources/15_patches-rooms_tumonline.yaml
data/sources/45_custom-maps.yaml
data/sources/46_overlay-maps.yaml
data/sources/img/img-sources.yaml
server/main-api/test/test-queries.yaml
deployment/k3s
91 changes: 91 additions & 0 deletions server/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@ opt-level = 3
# https://github.com/launchbadge/sqlx?tab=readme-ov-file#compile-time-verification
[profile.dev.package.sqlx-macros]
opt-level = 3

# https://insta.rs/docs/quickstart/
[profile.dev.package]
insta.opt-level = 3
similar.opt-level = 3
1 change: 1 addition & 0 deletions server/main-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ base64 = "0.22.1"
time = "0.3.36"

[dev-dependencies]
insta = { version = "1.39.0", features = ["yaml", "json", "redactions"] }
pretty_assertions = "1.4.0"
testcontainers = { version = "0.20.0", features = ["watchdog"] }
testcontainers-modules = { version = "0.8.0", features = ["postgres", "meilisearch"] }
Expand Down
9 changes: 9 additions & 0 deletions server/main-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,15 @@ some fuzzing-goals are automatically tested in our CI.
You can exchange `--base-url=http://localhost:3003` to `--base-url=https://nav.tum.de` for the full public API, or
restrict your scope using an option like `--endpoint=/api/search`.

### Approval tests

Some of our tests are approval tests.
Please install [insta](https://insta.rs/docs/quickstart/) to have a working environment.

You can then run `cargo insta test` instead of `cargo test` to review the needed changes.
If you don't want to do this, using the version we provide via CI is fine, but the DX is way better with the correct
tooling.

## License

This program is free software: you can redistribute it and/or modify
Expand Down
108 changes: 30 additions & 78 deletions server/main-api/src/calendar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,10 @@ mod tests {
.insert_header(ContentType::json())
.to_request();
let (_, resp) = test::call_service(&app, req).await.into_parts();
run_testcase(
resp,
400,
"Json deserialize error: EOF while parsing a value at line 1 column 0",
)
.await;

let (status, actual) = run_testcase(resp).await;
assert_eq!(status, 400);
insta::assert_snapshot!(actual, @r###""Json deserialize error: EOF while parsing a value at line 1 column 0""###);
}
{
// missing required query parameters
Expand All @@ -314,7 +312,10 @@ mod tests {
.insert_header(ContentType::json())
.to_request();
let (_, resp) = test::call_service(&app, req).await.into_parts();
run_testcase(resp, 400, "No id requested").await;

let (status, actual) = run_testcase(resp).await;
assert_eq!(status, 400);
insta::assert_snapshot!(actual, @r###""No id requested""###);
}
{
// way too many parameters
Expand All @@ -329,7 +330,10 @@ mod tests {
.insert_header(ContentType::json())
.to_request();
let (_, resp) = test::call_service(&app, req).await.into_parts();
run_testcase(resp, 400, "Too many ids to query. We suspect that users don't need this. If you need this limit increased, please send us a message").await;

let (status, actual) = run_testcase(resp).await;
assert_eq!(status, 400);
insta::assert_snapshot!(actual, @r###""Too many ids to query. We suspect that users don't need this. If you need this limit increased, please send us a message""###);
}
{
// room without a calendar
Expand All @@ -344,7 +348,10 @@ mod tests {
.insert_header(ContentType::json())
.to_request();
let (_, resp) = test::call_service(&app, req).await.into_parts();
run_testcase(resp, 404, "Room 5121.EG.002/None does not have a calendar").await;

let (status, actual) = run_testcase(resp).await;
assert_eq!(status, 404);
insta::assert_snapshot!(actual, @r###""Room 5121.EG.002/None does not have a calendar""###);
}
{
// show all entries of 5121.EG.003
Expand All @@ -359,43 +366,10 @@ mod tests {
.insert_header(ContentType::json())
.to_request();
let (_, resp) = test::call_service(&app, req).await.into_parts();
let expected = serde_json::json!({
"5121.EG.003": {
"events": [
{
"id": 1,
"room_code": "5121.EG.003",
"start_at": "2012-01-01T01:00:00Z",
"end_at": "2014-01-01T01:00:00Z",
"stp_title_de": "Quantenteleportation",
"stp_title_en": "Quantum teleportation",
"stp_type": "Vorlesung mit Zentralübung",
"entry_type": "lecture",
"detailed_entry_type": "Abhaltung"
},
{
"id": 2,
"room_code": "5121.EG.003",
"start_at": "2014-01-01T01:00:00Z",
"end_at": "2016-01-01T01:00:00Z",
"stp_title_de": "Quantenteleportation 2",
"stp_title_en": "Quantum teleportation 2",
"stp_type": "Vorlesung mit Zentralübung",
"entry_type": "lecture",
"detailed_entry_type": "Abhaltung"
}
],
"location": {
"key": "5121.EG.003",
"name": "5121.EG.003 (Computerraum)",
"last_calendar_scrape_at": now,
"calendar_url": "https://campus.tum.de/3",
"type_common_name": "Serverraum",
"type": "room"
}
}
});
run_testcase(resp, 200, &expected.to_string()).await;

let (status, actual) = run_testcase(resp).await;
assert_eq!(status, 200);
insta::assert_yaml_snapshot!(actual, {".**.last_calendar_scrape_at" => "[last_calendar_scrape_at]"});
}
{
// show both rooms, but a limited timeframe
Expand All @@ -410,46 +384,24 @@ mod tests {
.insert_header(ContentType::json())
.to_request();
let (_, resp) = test::call_service(&app, req).await.into_parts();
let expected = serde_json::json!({
"5121.EG.001": {
"events": [],
"location": {
"calendar_url": "https://campus.tum.de/1",
"key": "5121.EG.001",
"last_calendar_scrape_at": now,
"name": "5121.EG.001 (Montage- und Versuchshalle)",
"type": "room",
"type_common_name": "Versuchshalle",
},
},
"5121.EG.003": {
"events": [],
"location": {
"calendar_url": "https://campus.tum.de/3",
"key": "5121.EG.003",
"last_calendar_scrape_at": now,
"name": "5121.EG.003 (Computerraum)",
"type": "room",
"type_common_name": "Serverraum",
},
},
});
run_testcase(resp, 200, &expected.to_string()).await;

let (status, actual) = run_testcase(resp).await;
assert_eq!(status, 200);
insta::assert_yaml_snapshot!(actual, {".**.last_calendar_scrape_at" => "[last_calendar_scrape_at]"});
}
}

async fn run_testcase(resp: HttpResponse, expected_status: u16, expected_body: &str) {
async fn run_testcase(resp: HttpResponse) -> (u16, Value) {
let actual_status = resp.status().as_u16();
let body_box = resp.into_body();
let body_bytes = actix_web::body::to_bytes(body_box).await.unwrap();
let body_text = String::from_utf8(body_bytes.into_iter().collect()).unwrap();
// if the expected value cleanly deserializes into json, we should compare using this
if let Ok(expected_value) = serde_json::from_str::<Value>(expected_body) {
let actual_value = serde_json::from_str::<Value>(&body_text).unwrap();
assert_eq!(actual_value, expected_value);
let body = if let Ok(actual) = serde_json::from_str::<Value>(&body_text) {
actual
} else {
assert_eq!(body_text, expected_body);
}
assert_eq!(actual_status, expected_status);
Value::String(body_text)
};
(actual_status, body)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
source: main-api/src/calendar/mod.rs
expression: actual
---
5121.EG.003:
events:
- detailed_entry_type: Abhaltung
end_at: "2014-01-01T01:00:00Z"
entry_type: lecture
id: 1
room_code: 5121.EG.003
start_at: "2012-01-01T01:00:00Z"
stp_title_de: Quantenteleportation
stp_title_en: Quantum teleportation
stp_type: Vorlesung mit Zentralübung
- detailed_entry_type: Abhaltung
end_at: "2016-01-01T01:00:00Z"
entry_type: lecture
id: 2
room_code: 5121.EG.003
start_at: "2014-01-01T01:00:00Z"
stp_title_de: Quantenteleportation 2
stp_title_en: Quantum teleportation 2
stp_type: Vorlesung mit Zentralübung
location:
calendar_url: "https://campus.tum.de/3"
key: 5121.EG.003
last_calendar_scrape_at: "[last_calendar_scrape_at]"
name: 5121.EG.003 (Computerraum)
type: room
type_common_name: Serverraum
Loading

0 comments on commit 9d1b65e

Please sign in to comment.