From 8dafbaa1add4220ae765f84ebd114513a27f0310 Mon Sep 17 00:00:00 2001 From: gram Date: Sun, 16 Nov 2025 15:31:17 +0100 Subject: [PATCH] firefly_cli test --- src/args.rs | 7 +++++++ src/cli.rs | 1 + src/commands/mod.rs | 2 ++ src/commands/test.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 src/commands/test.rs diff --git a/src/args.rs b/src/args.rs index 7a10f47..bc6b91e 100644 --- a/src/args.rs +++ b/src/args.rs @@ -33,6 +33,10 @@ pub enum Commands { /// Launch firefly-emulator. Emulator(EmulatorArgs), + /// Run tests. + #[clap(alias("tests"), alias("pytest"))] + Test(TestArgs), + /// List all badges (aka achievements) defined in the given app. #[clap(alias("badge"), alias("achievements"), alias("achievement"))] Badges(BadgesArgs), @@ -160,6 +164,9 @@ pub struct NameSetArgs { pub name: String, } +#[derive(Debug, Parser)] +pub struct TestArgs {} + #[derive(Debug, Parser, Default)] pub struct BuildArgs { /// Path to the project root. diff --git a/src/cli.rs b/src/cli.rs index 96bd420..e629f69 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -10,6 +10,7 @@ pub fn run_command(vfs: PathBuf, command: &Commands) -> anyhow::Result<()> { Export(args) => cmd_export(&vfs, args), Import(args) => cmd_import(&vfs, args), New(args) => cmd_new(args), + Test(args) => cmd_test(args), Emulator(args) => cmd_emulator(args), Badges(args) => cmd_badges(&vfs, args), Boards(args) => cmd_boards(&vfs, args), diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 5f7860f..0cee580 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -15,6 +15,7 @@ mod new; mod repl; mod runtime; mod shots; +mod test; mod vfs; pub use badges::cmd_badges; @@ -34,4 +35,5 @@ pub use new::cmd_new; pub use repl::cmd_repl; pub use runtime::{cmd_exit, cmd_id, cmd_launch, cmd_restart, cmd_screenshot}; pub use shots::cmd_shots_download; +pub use test::cmd_test; pub use vfs::cmd_vfs; diff --git a/src/commands/test.rs b/src/commands/test.rs new file mode 100644 index 0000000..0df5c07 --- /dev/null +++ b/src/commands/test.rs @@ -0,0 +1,40 @@ +use crate::{args::TestArgs, langs::check_output}; +use anyhow::{bail, Context, Ok, Result}; +use std::{path::Path, process::Command}; + +/// Run tests. +pub fn cmd_test(_args: &TestArgs) -> Result<()> { + let venv_path = Path::new(".venv"); + let bin_path = venv_path.join("bin"); + let pytest_path = bin_path.join("pytest"); + + // Ensure venv exists. + if !venv_path.is_dir() { + println!("⏳️ creating venv..."); + let mut cmd = Command::new("python3"); + let cmd = cmd.args(["-m", "venv", ".venv"]); + let output = cmd.output().context("create venv")?; + check_output(&output).context("create venv")?; + } + + // Ensure pytest and firefly-test are installed. + if !pytest_path.is_file() { + println!("⏳️ installing dependencies..."); + let pip_path = bin_path.join("pip"); + let mut cmd = Command::new(&pip_path); + let cmd = cmd.args(["install", "pytest", "firefly-test"]); + let output = cmd.output().context("install firefly-test")?; + check_output(&output).context("install firefly-test")?; + } + + // Run pytest + println!("⏳️ running pytest..."); + let mut cmd = Command::new(&pytest_path); + let status = cmd.status().context("run pytest")?; + if !status.success() { + let code = status.code().unwrap_or(1); + bail!("subprocess exited with status code {code}"); + } + + Ok(()) +}