feat(runner): TestRunner registration + sequential execution (#9) #27
No reviewers
Labels
No labels
area:assertions
area:cli
area:client
area:harness
area:meta
area:reporting
area:runner
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/ws-rpc-test!27
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/9-runner-sequential"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #9. Stacked on #26.
Summary
Baseline test runner: register closures, start harness, connect client, execute sequentially, report. Hooks (#10), filtering/skip/fail-fast (#11), parallel mode (#12), and the coloured reporter (#13) arrive in later PRs.
API
Internals
TestCase { name, tags, body }wherebodyis stored asBox<dyn Fn(Arc<RpcClient>) -> Pin<Box<dyn Future<Output = TestResult> + Send + 'static>> + Send + Sync>.TestRunner.test(...)returns&mut TestCaseso chaining.tag("foo")works.run()starts the harness, connects the client, iterates tests sequentially withtokio::time::timeout(config.timeout, ...), records results, stops the harness.Ok(())→PassedErr(TestError::Skip(reason))→Skipped(reason preserved)Err→Failedwith the errorFailedwithTestError::Timeout { event: "test", duration }RunConfig { timeout: 60s default }— filtering / format / parallel fields land in their own tickets.Checklist (from issue #9)
Registration
TestRunner::new(harness)takes ownershiprunner.test(name, closure)returns&mut TestCasefor chainingArc<RpcClient> → impl Future<Output = TestResult>,'static + SendRun
TestReportRunConfig.timeout, default 60 s)Per-test outcome
Ok(())→ passedErr(TestError::Skip(_))→ skipped with reasonReport
TestReport { tests, passed, failed, skipped, filtered, duration }TestCaseResult { name, tags, status, duration, error, skip_reason }Test plan (7 new tests)
runner_registers_and_exposes_tagsrunner_executes_passing_test— in-process HTTP + WS echo fixtures, assertspassed == 1runner_reports_failure_from_err— test returnsTestError::Assertion, asserts status + errorrunner_reports_skip_from_skip_variant— test returnsTestError::Skip("requires network"), asserts reasonrunner_applies_per_test_timeout— 100 ms timeout, test sleeps 2 s, assertsTestError::Timeout { event: "test" }runner_returns_err_when_harness_fails_to_start— closed port, 300 ms startup deadline, assertsTestError::Connectionrunner_runs_multiple_tests_in_order— three tests, asserts orderingjust qagreen locally — 69/69 unit testsNotes for the reviewer
spawn_health_server,spawn_ws_echo_server) duplicate some code fromharness.rs/client.rstests. That's intentional for now — extracting a sharedtest_utilsmodule would be its own refactor. All three test modules will converge on the mock server from ticket #16.TestRunner::default()is now a real derived impl (clippy caught the manual one earlier).ProcessHarness::default(),RunConfig::default(), andVec::default()all derive-compose cleanly.tag()method onTestCasereturns&mut Selfso additional chained tags compose naturally.Review — TestRunner registration + exécution séquentielle (#9)
Design général
BoxedTestFn = Box<dyn Fn(...)>— le corps de test estFn(pasFnOnce), ce qui le rend réutilisable. Les tests pourraient théoriquement être re-run. C'est un choix délibéré ou une conséquence de l'API de la PR#12 (parallel) qui drain les tests ? À confirmer.test()retourne&mut TestCasepour permettre le chaînage.tag(...)— API ergonomique.run()— inlineprintln!La sortie console est gérée directement dans
run()avec desprintln!. Elle sera remplacée parConsoleReporteren PR#13. Pas de problème puisque c'est une PR intermédiaire.run_one— gestion duTestError::SkipÉlégant — l'utilisateur peut retourner
Err(TestError::Skip(...))depuis son corps de test pour un skip runtime. Compatible avecskip_ifqui arrive en #11.Tests
runner_applies_per_test_timeoutavec un sleep de 2s dans le corps — test direct de l'enforcement du timeout.runner_returns_err_when_harness_fails_to_start— vérifie que le client n'essaie pas de se connecter si le harness échoue.Aucun bloquant.
✅ Pas de bloquant — runner séquentiel propre, gestion du Skip élégante via
TestError::Skip.