Skip to content

Commit f9733da

Browse files
Reorganize files with messages in forge (#3834)
<!-- Reference any GitHub issues resolved by this PR --> Closes # ## Introduced changes <!-- A brief description of the changes --> - ## Checklist <!-- Make sure all of these are complete --> - [ ] Linked relevant issue - [ ] Updated relevant documentation - [ ] Added relevant tests - [ ] Performed self-review of the code - [ ] Added changes to `CHANGELOG.md`
1 parent b2532be commit f9733da

File tree

13 files changed

+272
-239
lines changed

13 files changed

+272
-239
lines changed

crates/forge-runner/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub mod package_tests;
3333
pub mod profiler_api;
3434
pub mod test_case_summary;
3535
pub mod test_target_summary;
36+
pub mod tests_summary;
3637

3738
pub mod backtrace;
3839
pub mod debugging;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use crate::test_target_summary::TestTargetSummary;
2+
use serde::Serialize;
3+
4+
// TODO(#2574): Bring back "filtered out" number in tests summary when running with `--exact` flag
5+
#[derive(Serialize)]
6+
pub struct TestsSummary {
7+
passed: usize,
8+
failed: usize,
9+
interrupted: usize,
10+
ignored: usize,
11+
filtered: Option<usize>,
12+
}
13+
14+
impl TestsSummary {
15+
#[must_use]
16+
pub fn new(summaries: &[TestTargetSummary], filtered: Option<usize>) -> Self {
17+
let passed = summaries.iter().map(TestTargetSummary::count_passed).sum();
18+
let failed = summaries.iter().map(TestTargetSummary::count_failed).sum();
19+
let interrupted = summaries
20+
.iter()
21+
.map(TestTargetSummary::count_interrupted)
22+
.sum();
23+
let ignored = summaries.iter().map(TestTargetSummary::count_ignored).sum();
24+
25+
Self {
26+
passed,
27+
failed,
28+
interrupted,
29+
ignored,
30+
filtered,
31+
}
32+
}
33+
34+
#[must_use]
35+
pub fn format_summary_message(&self) -> String {
36+
let filtered = self
37+
.filtered
38+
.map_or_else(|| "other".to_string(), |v| v.to_string());
39+
40+
let interrupted = if self.interrupted > 0 {
41+
format!("\nInterrupted execution of {} test(s).", self.interrupted)
42+
} else {
43+
String::new()
44+
};
45+
46+
format!(
47+
"{} passed, {} failed, {} ignored, {filtered} filtered out{interrupted}",
48+
self.passed, self.failed, self.ignored,
49+
)
50+
}
51+
}

crates/forge/src/run_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
pub mod maat;
2+
pub mod messages;
23
pub mod package;
34
pub mod resolve_config;
4-
pub mod structs;
55
pub mod test_target;
66
pub mod workspace;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
use console::style;
2+
use foundry_ui::Message;
3+
use serde::Serialize;
4+
use serde_json::{Value, json};
5+
6+
#[derive(Serialize)]
7+
pub struct CollectedTestsCountMessage {
8+
pub tests_num: usize,
9+
pub package_name: String,
10+
}
11+
12+
impl Message for CollectedTestsCountMessage {
13+
fn text(&self) -> String {
14+
let full = format!(
15+
"\n\nCollected {} test(s) from {} package",
16+
self.tests_num, self.package_name
17+
);
18+
style(full).bold().to_string()
19+
}
20+
21+
fn json(&self) -> Value {
22+
json!(self)
23+
}
24+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use foundry_ui::Message;
2+
use serde::Serialize;
3+
use serde_json::{Value, json};
4+
use std::{collections::HashMap, fmt::Write};
5+
6+
#[derive(Serialize)]
7+
pub struct LatestBlocksNumbersMessage {
8+
url_to_latest_block_number_map: HashMap<url::Url, starknet_api::block::BlockNumber>,
9+
}
10+
11+
impl LatestBlocksNumbersMessage {
12+
#[must_use]
13+
pub fn new(
14+
url_to_latest_block_number_map: HashMap<url::Url, starknet_api::block::BlockNumber>,
15+
) -> Self {
16+
Self {
17+
url_to_latest_block_number_map,
18+
}
19+
}
20+
}
21+
22+
impl Message for LatestBlocksNumbersMessage {
23+
fn text(&self) -> String {
24+
let mut output = String::new();
25+
output = format!("{output}\n");
26+
27+
for (url, latest_block_number) in &self.url_to_latest_block_number_map {
28+
let _ = writeln!(
29+
&mut output,
30+
"Latest block number = {latest_block_number} for url = {url}"
31+
);
32+
}
33+
34+
output
35+
}
36+
37+
fn json(&self) -> Value {
38+
json!(self)
39+
}
40+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pub mod collected_tests_count;
2+
pub mod latest_blocks_numbers;
3+
pub mod overall_summary;
4+
pub mod tests_failure_summary;
5+
pub mod tests_run;
6+
pub mod tests_summary;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use console::style;
2+
use forge_runner::test_target_summary::TestTargetSummary;
3+
use forge_runner::tests_summary::TestsSummary;
4+
use foundry_ui::{Message, components::labeled::LabeledMessage};
5+
use serde::Serialize;
6+
use serde_json::{Value, json};
7+
8+
#[derive(Serialize)]
9+
pub struct OverallSummaryMessage {
10+
summary: TestsSummary,
11+
}
12+
13+
impl OverallSummaryMessage {
14+
pub const LABEL: &str = "Tests summary";
15+
16+
#[must_use]
17+
pub fn new(summaries: &[TestTargetSummary], filtered: Option<usize>) -> Self {
18+
Self {
19+
summary: TestsSummary::new(summaries, filtered),
20+
}
21+
}
22+
}
23+
24+
impl Message for OverallSummaryMessage {
25+
fn text(&self) -> String {
26+
let styled_label = style(&Self::LABEL).bold().to_string();
27+
LabeledMessage::new(&styled_label, &self.summary.format_summary_message()).text()
28+
}
29+
30+
fn json(&self) -> Value {
31+
json!(self)
32+
}
33+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
use console::style;
2+
use forge_runner::test_case_summary::AnyTestCaseSummary;
3+
use foundry_ui::Message;
4+
use serde::Serialize;
5+
use serde_json::{Value, json};
6+
use std::fmt::Write;
7+
8+
#[derive(Serialize)]
9+
pub struct TestsFailureSummaryMessage {
10+
pub failed_test_names: Vec<String>,
11+
}
12+
13+
impl TestsFailureSummaryMessage {
14+
#[must_use]
15+
pub fn new(all_failed_tests: &[AnyTestCaseSummary]) -> Self {
16+
let failed_test_names = all_failed_tests
17+
.iter()
18+
.map(|any_test_case_summary| any_test_case_summary.name().unwrap().to_string())
19+
.collect();
20+
21+
Self { failed_test_names }
22+
}
23+
}
24+
25+
impl Message for TestsFailureSummaryMessage {
26+
fn text(&self) -> String {
27+
if self.failed_test_names.is_empty() {
28+
return String::new();
29+
}
30+
31+
let mut failures = "\nFailures:".to_string();
32+
for name in &self.failed_test_names {
33+
let _ = write!(&mut failures, "\n {name}");
34+
}
35+
style(failures).bold().to_string()
36+
}
37+
38+
fn json(&self) -> Value {
39+
json!(self)
40+
}
41+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use console::style;
2+
use forge_runner::package_tests::TestTargetLocation;
3+
use foundry_ui::Message;
4+
use serde::Serialize;
5+
use serde_json::{Value, json};
6+
7+
#[derive(Serialize)]
8+
pub struct TestsRunMessage {
9+
test_target_location: TestTargetLocation,
10+
tests_num: usize,
11+
}
12+
13+
impl TestsRunMessage {
14+
#[must_use]
15+
pub fn new(test_target_location: TestTargetLocation, tests_num: usize) -> Self {
16+
Self {
17+
test_target_location,
18+
tests_num,
19+
}
20+
}
21+
}
22+
23+
impl Message for TestsRunMessage {
24+
fn text(&self) -> String {
25+
let dir_name = match self.test_target_location {
26+
TestTargetLocation::Lib => "src",
27+
TestTargetLocation::Tests => "tests",
28+
};
29+
let plain_text = format!("Running {} test(s) from {}/", self.tests_num, dir_name);
30+
style(plain_text).bold().to_string()
31+
}
32+
33+
fn json(&self) -> Value {
34+
json!(self)
35+
}
36+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use console::style;
2+
use forge_runner::{test_target_summary::TestTargetSummary, tests_summary::TestsSummary};
3+
use foundry_ui::{Message, components::labeled::LabeledMessage};
4+
use serde::Serialize;
5+
use serde_json::{Value, json};
6+
7+
#[derive(Serialize)]
8+
pub struct TestsSummaryMessage {
9+
summary: TestsSummary,
10+
}
11+
12+
impl TestsSummaryMessage {
13+
pub const LABEL: &str = "Tests";
14+
15+
#[must_use]
16+
pub fn new(summaries: &[TestTargetSummary], filtered: Option<usize>) -> Self {
17+
Self {
18+
summary: TestsSummary::new(summaries, filtered),
19+
}
20+
}
21+
}
22+
23+
impl Message for TestsSummaryMessage {
24+
fn text(&self) -> String {
25+
let styled_label = style(&Self::LABEL).bold().to_string();
26+
LabeledMessage::new(&styled_label, &self.summary.format_summary_message()).text()
27+
}
28+
29+
fn json(&self) -> Value {
30+
json!(self)
31+
}
32+
}

0 commit comments

Comments
 (0)