From 269fdab3a13207c3b80073cedd1d69e888b934f1 Mon Sep 17 00:00:00 2001 From: Fadi Hanna Al-Kass Date: Mon, 30 Jun 2025 08:19:55 -0700 Subject: [PATCH 1/4] Migrate CI to GitHub Actions, update deps and fix logging --- .github/workflows/build.yml | 10 +++++++--- .travis.yml | 14 -------------- Cargo.toml | 8 ++++---- README.md | 2 +- src/lib.rs | 4 ---- src/logger.rs | 2 +- src/test_case.rs | 16 ++++++++-------- 7 files changed, 21 insertions(+), 35 deletions(-) delete mode 100644 .travis.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3af63ef..0c94d96 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,6 +12,10 @@ on: jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + rust: [stable, beta, nightly] + fail-fast: false steps: - name: Check out the repository @@ -20,7 +24,7 @@ jobs: - name: Set up Rust uses: actions-rs/toolchain@v1 with: - toolchain: stable + toolchain: ${{ matrix.rust }} override: true - name: Cache Cargo registry @@ -48,10 +52,10 @@ jobs: ${{ runner.os }}-cargo-build- - name: Build - run: cargo build --verbose + run: cargo build --release --verbose - name: Run tests - run: cargo test --verbose + run: make test - name: Run Clippy run: cargo clippy -- -D warnings diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1c15489..0000000 --- a/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -sudo: required -language: rust -os: - - linux -rust: - - stable - - beta - - nightly -matrix: - allow_failures: - - rust: nightly -script: -- cargo build --release -- make test diff --git a/Cargo.toml b/Cargo.toml index bfe2e05..3dfd3fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,11 +10,11 @@ readme = "README.md" keywords = ["Rust", "Testing", "Test-Driven"] categories = ["development-tools::testing"] license = "MIT" +edition = "2021" [badges] -travis-ci = { repository = "Alkass/polish" } +github-actions = { repository = "Alkass/polish", workflow = "Rust CI" } [dependencies] -chrono = "0.3.0" -ansi_term = "0.9.0" -time = "0.1.37" +chrono = "0.4" +ansi_term = "0.12" diff --git a/README.md b/README.md index 389fbc0..bb76c03 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/Alkass/polish.svg?branch=master)](https://travis-ci.org/Alkass/polish) +[![CI Status](https://github.com/AlKass/polish/actions/workflows/build.yml/badge.svg)](https://github.com/AlKass/polish/actions) [![Crates Package Status](https://img.shields.io/crates/v/polish.svg)](https://crates.io/crates/polish) [![](https://docs.rs/polish/badge.svg)](https://docs.rs/polish) [![](https://img.shields.io/crates/d/polish.svg)](https://crates.io/crates/polish) diff --git a/src/lib.rs b/src/lib.rs index 962cfb6..0799bd7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,2 @@ -extern crate chrono; -extern crate ansi_term; -extern crate time; - pub mod logger; pub mod test_case; diff --git a/src/logger.rs b/src/logger.rs index 9443d36..b2725c0 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -71,7 +71,7 @@ impl Logger { pub fn get_num_info(&self) -> i32 { self._info } - pub fn drop(&mut self) { + pub fn summary(&mut self) { let formatted_pass = format!("{} {}", self.get_num_pass(), Green.paint("PASS")); let formatted_fail = format!("{} {}", self.get_num_fail(), Red.paint("FAIL")); let formatted_warn = format!("{} {}", self.get_num_warn(), Yellow.paint("WARN")); diff --git a/src/test_case.rs b/src/test_case.rs index 70c94da..3b1d5f8 100644 --- a/src/test_case.rs +++ b/src/test_case.rs @@ -1,8 +1,8 @@ -use time; +use std::time::Instant; use chrono::prelude::Local; use ansi_term::Colour; use ansi_term::Colour::{Green, Red, Yellow}; -use logger::Logger; +use crate::logger::Logger; #[derive(PartialEq, Clone)] pub enum TestCaseStatus { @@ -15,12 +15,12 @@ pub enum TestCaseStatus { pub struct TestCase { pub title: &'static str, pub criteria: &'static str, - pub exec: Box TestCaseStatus>, + pub exec: Box TestCaseStatus>, } impl TestCase { pub fn new(title: &'static str, criteria: &'static str, - exec: Box TestCaseStatus>) + exec: Box TestCaseStatus>) -> TestCase { TestCase { title: title, @@ -120,15 +120,15 @@ impl TestRunner { Local::now().format("%Y-%m-%d").to_string()); } let mut logger: Logger = Logger::new(); - let starting_time: i32 = time::now().tm_nsec; + let start_time = Instant::now(); let mut status: TestCaseStatus = (test.exec)(&mut logger); - let ending_time: i32 = time::now().tm_nsec; + let duration_ns = start_time.elapsed().as_nanos() as DurationType; if !self.has_attribute(TEST_RUNNER_ATTRIBUTES.minimize_output) { println!("Ended {} at {} on {}", test.title, Local::now().format("%H:%M:%S").to_string(), Local::now().format("%Y-%m-%d").to_string()); - logger.drop(); + logger.summary(); } if status == TestCaseStatus::UNKNOWN { if logger.get_num_fail() > 0 { @@ -149,7 +149,7 @@ impl TestRunner { TestCaseStatus::SKIPPED => Yellow.paint(test.criteria), TestCaseStatus::UNKNOWN => Yellow.paint(test.criteria), }; - let mut duration: DurationType = (ending_time - starting_time) as DurationType; + let mut duration: DurationType = duration_ns; if self.time_unit == TEST_RUNNER_TIME_UNITS.minutes { duration /= 1000000000 as DurationType; duration /= 60 as DurationType; From 2d470ca99e6574de9d027b7103c9a6a3200c8f2f Mon Sep 17 00:00:00 2001 From: Fadi Hanna Al-Kass Date: Mon, 30 Jun 2025 08:23:44 -0700 Subject: [PATCH 2/4] Install clippy and rustfmt in CI --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c94d96..d6c30e9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,6 +25,7 @@ jobs: uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.rust }} + components: clippy, rustfmt override: true - name: Cache Cargo registry From ab97fbf68b0f29fc71a3e03d0904462d739dfb42 Mon Sep 17 00:00:00 2001 From: Fadi Hanna Al-Kass Date: Mon, 30 Jun 2025 08:40:05 -0700 Subject: [PATCH 3/4] Fix clippy warnings --- src/logger.rs | 20 ++++++++++-------- src/test_case.rs | 55 ++++++++++++++++++++++++------------------------ 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/logger.rs b/src/logger.rs index b2725c0..495025c 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -14,6 +14,12 @@ pub struct Logger { _warn: i32, _info: i32, } + +impl Default for Logger { + fn default() -> Self { + Self::new() + } +} impl Logger { pub fn new() -> Logger { Logger { @@ -72,14 +78,10 @@ impl Logger { self._info } pub fn summary(&mut self) { - let formatted_pass = format!("{} {}", self.get_num_pass(), Green.paint("PASS")); - let formatted_fail = format!("{} {}", self.get_num_fail(), Red.paint("FAIL")); - let formatted_warn = format!("{} {}", self.get_num_warn(), Yellow.paint("WARN")); - let formatted_info = format!("{} {}", self.get_num_info(), Cyan.paint("INFO")); - println!("{} {} {} {}", - formatted_pass, - formatted_fail, - formatted_warn, - formatted_info); + let formatted_pass = Green.paint(format!("{pass} Passed", pass = self.get_num_pass())); + let formatted_fail = Red.paint(format!("{fail} Failed", fail = self.get_num_fail())); + let formatted_warn = Yellow.paint(format!("{warn} Warn", warn = self.get_num_warn())); + let formatted_info = Cyan.paint(format!("{info} Info", info = self.get_num_info())); + println!("{formatted_pass} {formatted_fail} {formatted_warn} {formatted_info}"); } } diff --git a/src/test_case.rs b/src/test_case.rs index 3b1d5f8..87950a2 100644 --- a/src/test_case.rs +++ b/src/test_case.rs @@ -22,11 +22,7 @@ impl TestCase { criteria: &'static str, exec: Box TestCaseStatus>) -> TestCase { - TestCase { - title: title, - criteria: criteria, - exec: exec, - } + TestCase { title, criteria, exec } } } @@ -84,6 +80,12 @@ pub struct TestRunner { results: Vec, module_path: &'static str, } + +impl Default for TestRunner { + fn default() -> Self { + Self::new() + } +} impl TestRunner { pub fn new() -> TestRunner { TestRunner { @@ -116,8 +118,8 @@ impl TestRunner { if !self.has_attribute(TEST_RUNNER_ATTRIBUTES.minimize_output) { println!("Starting {} at {} on {}", test.title, - Local::now().format("%H:%M:%S").to_string(), - Local::now().format("%Y-%m-%d").to_string()); + Local::now().format("%H:%M:%S"), + Local::now().format("%Y-%m-%d")); } let mut logger: Logger = Logger::new(); let start_time = Instant::now(); @@ -126,8 +128,8 @@ impl TestRunner { if !self.has_attribute(TEST_RUNNER_ATTRIBUTES.minimize_output) { println!("Ended {} at {} on {}", test.title, - Local::now().format("%H:%M:%S").to_string(), - Local::now().format("%Y-%m-%d").to_string()); + Local::now().format("%H:%M:%S"), + Local::now().format("%Y-%m-%d")); logger.summary(); } if status == TestCaseStatus::UNKNOWN { @@ -171,17 +173,17 @@ impl TestRunner { let test_info = TestCaseResults { title: test.title, criteria: test.criteria, - duration: duration, + duration, status: status.clone(), }; - if self.module_path.len() > 0 { + if !self.module_path.is_empty() { println!("{} {}::{}: {} ({:.*}{})",mark, self.module_path, test.title, formatted_criteria, precision, test_info.duration, self.time_unit.1); } else { println!("{} {}: {} ({:.*}{})",mark, test.title, formatted_criteria, precision, test_info.duration, self.time_unit.1); } self.results.push(test_info); - return status == TestCaseStatus::PASSED; + status == TestCaseStatus::PASSED } pub fn run_tests(&mut self, tests: Vec) -> bool { for test in tests { @@ -189,10 +191,10 @@ impl TestRunner { return false; } } - return true; + true } pub fn run_tests_from_class(&mut self, test_class: T) -> bool { - return self.run_tests(test_class.tests()); + self.run_tests(test_class.tests()) } } impl Drop for TestRunner { @@ -200,29 +202,26 @@ impl Drop for TestRunner { if !self.has_attribute(TEST_RUNNER_ATTRIBUTES.disable_final_stats) { let (mut total_count, mut total_duration): (i32, DurationType) = (0, 0 as DurationType); let (mut pass, mut fail, mut skip): (i32, i32, i32) = (0, 0, 0); - print!("\n"); + println!(); for stat in self.results.iter() { - let color: Colour; - match stat.status { + let color: Colour = match stat.status { TestCaseStatus::PASSED => { pass += 1; - color = Green; + Green }, TestCaseStatus::FAILED => { fail += 1; - color = Red; + Red }, TestCaseStatus::SKIPPED => { skip += 1; - color = Yellow; + Yellow }, - _ => { - color = Yellow; - } + _ => Yellow, }; total_count += 1; total_duration += stat.duration; - if self.module_path.len() > 0 { + if !self.module_path.is_empty() { println!("{}", color.paint(format!("{}::{}: {} ({}{})", self.module_path, stat.title, stat.criteria, stat.duration, self.time_unit.1))); } else { @@ -236,10 +235,10 @@ impl Drop for TestRunner { else { println!("\nRan {} tests in {}{}", total_count, total_duration, self.time_unit.1); } - let formatted_pass = Green.paint(format!("{} Passed", pass)); - let formatted_failed = Red.paint(format!("{} Failed", fail)); - let formatted_skipped = Yellow.paint(format!("{} Skipped", skip)); - println!("{} {} {}", formatted_pass, formatted_failed, formatted_skipped); + let formatted_pass = Green.paint(format!("{pass} Passed", pass = pass)); + let formatted_failed = Red.paint(format!("{fail} Failed", fail = fail)); + let formatted_skipped = Yellow.paint(format!("{skip} Skipped", skip = skip)); + println!("{formatted_pass} {formatted_failed} {formatted_skipped}"); } } } From 1f236870037c6f293b440d983f9e7dda320da179 Mon Sep 17 00:00:00 2001 From: Fadi Hanna Al-Kass Date: Mon, 30 Jun 2025 08:48:31 -0700 Subject: [PATCH 4/4] Fix clippy formatting strings --- src/test_case.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test_case.rs b/src/test_case.rs index 87950a2..ef8b9b9 100644 --- a/src/test_case.rs +++ b/src/test_case.rs @@ -235,9 +235,9 @@ impl Drop for TestRunner { else { println!("\nRan {} tests in {}{}", total_count, total_duration, self.time_unit.1); } - let formatted_pass = Green.paint(format!("{pass} Passed", pass = pass)); - let formatted_failed = Red.paint(format!("{fail} Failed", fail = fail)); - let formatted_skipped = Yellow.paint(format!("{skip} Skipped", skip = skip)); + let formatted_pass = Green.paint(format!("{pass} Passed")); + let formatted_failed = Red.paint(format!("{fail} Failed")); + let formatted_skipped = Yellow.paint(format!("{skip} Skipped")); println!("{formatted_pass} {formatted_failed} {formatted_skipped}"); } }