ace-test-runner 0.19.1 → 0.25.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ace-defaults/test/runner.yml +9 -9
- data/.ace-defaults/test-runner/config.yml +24 -20
- data/CHANGELOG.md +124 -0
- data/README.md +6 -4
- data/exe/ace-test-suite +10 -0
- data/lib/ace/test_runner/atoms/test_folder_detector.rb +4 -4
- data/lib/ace/test_runner/atoms/test_type_detector.rb +9 -5
- data/lib/ace/test_runner/cli/commands/test.rb +13 -9
- data/lib/ace/test_runner/formatters/progress_formatter.rb +25 -28
- data/lib/ace/test_runner/models/test_configuration.rb +26 -20
- data/lib/ace/test_runner/models/{test_group.rb → test_target.rb} +16 -20
- data/lib/ace/test_runner/molecules/cli_argument_parser.rb +2 -2
- data/lib/ace/test_runner/molecules/config_loader.rb +1 -1
- data/lib/ace/test_runner/molecules/pattern_resolver.rb +60 -39
- data/lib/ace/test_runner/molecules/smart_test_executor.rb +2 -2
- data/lib/ace/test_runner/organisms/{sequential_group_executor.rb → sequential_target_executor.rb} +28 -29
- data/lib/ace/test_runner/organisms/test_orchestrator.rb +26 -31
- data/lib/ace/test_runner/suite/process_monitor.rb +38 -6
- data/lib/ace/test_runner/suite/result_aggregator.rb +11 -1
- data/lib/ace/test_runner/version.rb +1 -1
- metadata +14 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a3b6dedacee5052d28f975648576a8c4cb055e7cd97189370d8ad6dd76187a3f
|
|
4
|
+
data.tar.gz: 77682af101a16be792fa0bff81c3991ab53907d1e20fa369e0f0a5b9a59742cd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5e48ad20281ddf07b11ff9a7287615d8c4905d0eec07e0c16bf106d50a8fe28e2f7d7539f5652cebd92aa0ff74e99853f6dbe5a42b424fd6441b2421db35d468
|
|
7
|
+
data.tar.gz: 50b021df7a49b9a1d9ea7d2b577feab71741ab59158a182ccf46c476b9153125c142b4bd409f60df08926fd2046fbf5cc1de4ed4190db1149b695874273eefa1
|
|
@@ -20,16 +20,16 @@ test:
|
|
|
20
20
|
|
|
21
21
|
# Test file patterns (optional - has good defaults)
|
|
22
22
|
# patterns:
|
|
23
|
-
# smoke: "test
|
|
24
|
-
# atoms: "test/atoms/**/*_test.rb"
|
|
25
|
-
# molecules: "test/molecules/**/*_test.rb"
|
|
26
|
-
# organisms: "test/organisms/**/*_test.rb"
|
|
27
|
-
# models: "test/models/**/*_test.rb"
|
|
28
|
-
#
|
|
29
|
-
# system: "test/system/**/*_test.rb"
|
|
23
|
+
# smoke: "test/{fast/,}smoke/**/*_test.rb"
|
|
24
|
+
# atoms: "test/{fast/,}atoms/**/*_test.rb"
|
|
25
|
+
# molecules: "test/{fast/,}molecules/**/*_test.rb"
|
|
26
|
+
# organisms: "test/{fast/,}organisms/**/*_test.rb"
|
|
27
|
+
# models: "test/{fast/,}models/**/*_test.rb"
|
|
28
|
+
# feat_tests: "test/feat/**/*_test.rb"
|
|
30
29
|
#
|
|
31
30
|
# Test groups (optional - has good defaults)
|
|
32
31
|
# groups:
|
|
33
|
-
#
|
|
34
|
-
#
|
|
32
|
+
# fast: [smoke, atoms, molecules, organisms, models]
|
|
33
|
+
# feat: [feat_tests]
|
|
34
|
+
# all: [fast, feat]
|
|
35
35
|
# quick: [atoms, molecules]
|
|
@@ -10,25 +10,23 @@
|
|
|
10
10
|
version: 1
|
|
11
11
|
|
|
12
12
|
# Test file patterns for each category
|
|
13
|
-
# Supports both test/unit/atoms and test/atoms directory structures
|
|
14
13
|
patterns:
|
|
15
|
-
smoke: "test/{
|
|
16
|
-
atoms: "test/{
|
|
17
|
-
molecules: "test/{
|
|
18
|
-
organisms: "test/{
|
|
19
|
-
models: "test/{
|
|
20
|
-
commands: "test/{
|
|
21
|
-
cli: "test/{
|
|
22
|
-
prompts: "test/{
|
|
23
|
-
fixtures: "test/{
|
|
24
|
-
support: "test/{
|
|
25
|
-
edge: "test/{
|
|
26
|
-
|
|
27
|
-
system: "test/system/**/*_test.rb"
|
|
14
|
+
smoke: "test/{fast/,}smoke/**/*_test.rb"
|
|
15
|
+
atoms: "test/{fast/,}atoms/**/*_test.rb"
|
|
16
|
+
molecules: "test/{fast/,}molecules/**/*_test.rb"
|
|
17
|
+
organisms: "test/{fast/,}organisms/**/*_test.rb"
|
|
18
|
+
models: "test/{fast/,}models/**/*_test.rb"
|
|
19
|
+
commands: "test/{fast/,}commands/**/*_test.rb"
|
|
20
|
+
cli: "test/{fast/,}cli/**/*_test.rb"
|
|
21
|
+
prompts: "test/{fast/,}prompts/**/*_test.rb"
|
|
22
|
+
fixtures: "test/{fast/,}fixtures/**/*_test.rb"
|
|
23
|
+
support: "test/{fast/,}support/**/*_test.rb"
|
|
24
|
+
edge: "test/{fast/,}edge/**/*_test.rb"
|
|
25
|
+
feat_tests: "test/feat/**/*_test.rb"
|
|
28
26
|
|
|
29
|
-
# Test
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
# Test targets that combine multiple patterns
|
|
28
|
+
targets:
|
|
29
|
+
fast:
|
|
32
30
|
- smoke
|
|
33
31
|
- atoms
|
|
34
32
|
- molecules
|
|
@@ -39,11 +37,12 @@ groups:
|
|
|
39
37
|
- prompts
|
|
40
38
|
- fixtures
|
|
41
39
|
- support
|
|
40
|
+
feat:
|
|
41
|
+
- feat_tests
|
|
42
42
|
- edge
|
|
43
43
|
all:
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
- system
|
|
44
|
+
- fast
|
|
45
|
+
- feat
|
|
47
46
|
quick:
|
|
48
47
|
- atoms
|
|
49
48
|
- molecules
|
|
@@ -59,3 +58,8 @@ defaults:
|
|
|
59
58
|
# Failure display limits
|
|
60
59
|
failure_limits:
|
|
61
60
|
max_display: 7
|
|
61
|
+
|
|
62
|
+
execution:
|
|
63
|
+
mode: by-target
|
|
64
|
+
target_fail_fast: true
|
|
65
|
+
target_isolation: false
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,130 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.25.7] - 2026-08-12
|
|
11
|
+
|
|
12
|
+
### Technical
|
|
13
|
+
- Raised the `ace-support-core` dependency floor to `~> 0.31` after the principles-first bootstrap guidance release.
|
|
14
|
+
## [0.25.6] - 2026-08-12
|
|
15
|
+
|
|
16
|
+
### Technical
|
|
17
|
+
- Aligned gemspec dependency floors with current ACE package minor release lines and safe external minor dependency bumps (no major version jumps).
|
|
18
|
+
|
|
19
|
+
## [0.25.5] - 2026-04-19
|
|
20
|
+
|
|
21
|
+
### Technical
|
|
22
|
+
- Tightened retained suite failure-propagation runner guidance to persist the injected failing-test path before precheck and cleanup steps.
|
|
23
|
+
|
|
24
|
+
## [0.25.4] - 2026-04-18
|
|
25
|
+
|
|
26
|
+
### Technical
|
|
27
|
+
- Strengthened retained suite failure-propagation E2E coverage so Goal 2 now proves the injected failing file through a direct `ace-test` precheck before validating `ace-test-suite` aggregate failure propagation.
|
|
28
|
+
|
|
29
|
+
## [0.25.3] - 2026-04-16
|
|
30
|
+
|
|
31
|
+
### Technical
|
|
32
|
+
- Reworked retained suite failure-propagation E2E setup to use a deterministic failing fast-test fixture and require non-zero exit evidence tied to the injected failure path.
|
|
33
|
+
|
|
34
|
+
## [0.25.2] - 2026-04-16
|
|
35
|
+
|
|
36
|
+
### Technical
|
|
37
|
+
- Updated `TS-TEST-001` and `TS-TEST-002` sandbox setup to source `mise.toml` from `${ACE_E2E_SOURCE_ROOT:-$PROJECT_ROOT_PATH}` so test-runner E2E flows remain compatible with the shared read-only source-root contract.
|
|
38
|
+
|
|
39
|
+
## [0.25.1] - 2026-04-15
|
|
40
|
+
|
|
41
|
+
### Fixed
|
|
42
|
+
- Corrected `TS-TEST-002` suite scenario command contracts to run `ace-test-suite` from sandbox `PATH` and aligned verifier expectations with the same public command surface.
|
|
43
|
+
|
|
44
|
+
## [0.25.0] - 2026-04-15
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
- Reworked `ace-test-runner` E2E suites to public-surface goal style by removing duplicate TS-TEST-001 group coverage, enforcing canonical TS-TEST-002 suite invocation, and adding suite `--target` pass-through scenario coverage.
|
|
48
|
+
- Updated `docs/usage.md` with canonical `ace-test-e2e ace-test-runner` guidance and explicit suite E2E invocation constraints.
|
|
49
|
+
|
|
50
|
+
## [0.24.2] - 2026-04-13
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
- Relaxed the removed `unit` target regression assertion so it verifies the canonical target set without depending on display order.
|
|
54
|
+
|
|
55
|
+
## [0.24.1] - 2026-04-13
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
- Completed the batch i05 migration follow-through for this package and aligned it with the restarted `fast` / `feat` / `e2e` verification model.
|
|
59
|
+
|
|
60
|
+
### Technical
|
|
61
|
+
- Included in the coordinated assignment-driven patch release for batch i05 package updates.
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## [0.24.0] - 2026-04-12
|
|
65
|
+
|
|
66
|
+
### Changed
|
|
67
|
+
- Migrated deterministic package tests to the `test/fast/` and `test/feat/` layout for `ace-test-runner`, including moving former `test/integration/` coverage into `feat`.
|
|
68
|
+
- Updated package defaults, fixture config, E2E scenario coverage references, and usage examples to align with the `fast` / `feat` / `e2e` contract.
|
|
69
|
+
|
|
70
|
+
### Removed
|
|
71
|
+
- Removed legacy `test/integration/` deterministic test directory from `ace-test-runner`.
|
|
72
|
+
|
|
73
|
+
## [0.23.0] - 2026-04-11
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
- Renamed package-level test-scope terminology to `target` across CLI, runtime, docs, and config, with `targets:` replacing `groups:` and `execution.mode: by-target` replacing the old grouped wording.
|
|
77
|
+
- Kept suite package bucketing on `group` so `ace-test-suite --group` continues to mean package selection while `--target` stays package-local test scope.
|
|
78
|
+
|
|
79
|
+
### Fixed
|
|
80
|
+
- Made `ace-test-suite --target feat` fail closed on current-run subprocess errors instead of reusing stale package summaries, so suite totals now reflect real feat-only execution.
|
|
81
|
+
|
|
82
|
+
### Technical
|
|
83
|
+
- Renamed sequential-execution and target-model internals to match the public `target` contract and added regression coverage for config loading, resolver cycles, explicit-file execution, and suite summary freshness.
|
|
84
|
+
|
|
85
|
+
## [0.22.0] - 2026-04-11
|
|
86
|
+
|
|
87
|
+
### Changed
|
|
88
|
+
- Renamed the public deterministic test contract to `fast` / `feat`, made bare `ace-test` default to `fast`, and made `all` execute `fast` then `feat`.
|
|
89
|
+
- Updated CLI help, configuration defaults, and suite target guidance to teach `ace-test-e2e` as the only scenario E2E entrypoint.
|
|
90
|
+
|
|
91
|
+
### Technical
|
|
92
|
+
- Kept internal compatibility aliases for `unit` and `integration` during the migration window while updating resolver and config-loader coverage to the new public naming.
|
|
93
|
+
|
|
94
|
+
## [0.21.0] - 2026-04-10
|
|
95
|
+
|
|
96
|
+
### Changed
|
|
97
|
+
- Changed bare `ace-test` package runs to default to the `unit` group, added `int` as an alias for `integration`, and narrowed `all` to `unit`, `edge`, and `integration`.
|
|
98
|
+
- Removed legacy `system`, `e2e`, and `all-with-e2e` targets from the CLI/docs surface and directed scenario E2E execution to `ace-test-e2e`.
|
|
99
|
+
|
|
100
|
+
## [0.20.1] - 2026-04-10
|
|
101
|
+
|
|
102
|
+
### Fixed
|
|
103
|
+
- Honored an explicitly configured `all` target without widening default package runs into `test/e2e`, restoring the intended non-E2E default selection.
|
|
104
|
+
|
|
105
|
+
## [0.20.0] - 2026-04-10
|
|
106
|
+
|
|
107
|
+
### Changed
|
|
108
|
+
- Added a first-class `e2e` target for `ace-test` and `ace-test-suite --target e2e`, while keeping default `all` runs non-E2E.
|
|
109
|
+
- Documented suite-level E2E targeting and updated runner defaults around the restarted deterministic E2E flow.
|
|
110
|
+
|
|
111
|
+
## [0.19.6] - 2026-04-10
|
|
112
|
+
|
|
113
|
+
### Fixed
|
|
114
|
+
- Restored suite-enforced `--run-in-single-batch` execution so `ace-test-suite` preserves its package execution contract instead of falling back to grouped runs.
|
|
115
|
+
- Prefer live runtime timeout/failure state over stale `latest/summary.json` data so suite aggregation no longer reports timed-out packages as passed.
|
|
116
|
+
- Detect subprocess-sensitive tests by file content even inside unit directories, preventing single-batch in-process hangs for packages like `ace-test-runner-e2e`.
|
|
117
|
+
|
|
118
|
+
## [0.19.5] - 2026-04-10
|
|
119
|
+
|
|
120
|
+
### Fixed
|
|
121
|
+
- Stopped forcing `--run-in-single-batch` in suite package execution so `ace-test-suite` uses the stable grouped package path instead of the hanging single-batch mode.
|
|
122
|
+
- Prefer live runtime timeout/failure state over stale `latest/summary.json` data so suite aggregation no longer reports timed-out packages as passed.
|
|
123
|
+
|
|
124
|
+
## [0.19.3] - 2026-04-07
|
|
125
|
+
|
|
126
|
+
### Technical
|
|
127
|
+
- Expanded suite process-monitor timeout coverage for the full-suite integration queue scenario and improved failure-window robustness under concurrent execution.
|
|
128
|
+
|
|
129
|
+
## [0.19.2] - 2026-04-07
|
|
130
|
+
|
|
131
|
+
### Technical
|
|
132
|
+
- Stabilized suite process-monitor integration coverage by increasing the timeout budget for the queued-package timeout scenario under full-suite load.
|
|
133
|
+
|
|
10
134
|
## [0.19.1] - 2026-03-29
|
|
11
135
|
|
|
12
136
|
### Technical
|
data/README.md
CHANGED
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
|
|
19
19
|

|
|
20
20
|
|
|
21
|
-
`ace-test-runner` wraps [Minitest](https://github.com/minitest/minitest) with smart
|
|
21
|
+
`ace-test-runner` wraps [Minitest](https://github.com/minitest/minitest) with smart target resolution, cross-package execution, and persistent reports so both developers and coding agents can run focused checks quickly, diagnose failures with context, and retain searchable execution history. It handles the execution side of testing; use [ace-test](../ace-test) for planning, review, and suite improvement workflows.
|
|
22
22
|
|
|
23
23
|
## How It Works
|
|
24
24
|
|
|
25
|
-
1. Resolve the target package and test scope from a package name,
|
|
25
|
+
1. Resolve the target package and test scope from a package name, target (`atoms`, `molecules`, `organisms`, `models`, `fast`, `feat`, `all`, `quick`), or direct `file:line` selector.
|
|
26
26
|
2. Execute the matching tests with failure-oriented output and optional profiling of the slowest cases.
|
|
27
27
|
3. Persist structured run reports for historical debugging and searchable triage across runs.
|
|
28
28
|
|
|
@@ -30,11 +30,13 @@
|
|
|
30
30
|
|
|
31
31
|
**Run package tests from anywhere in the monorepo** - execute [`ace-test [package]`](docs/usage.md) by name without changing directories, keeping outputs consistent across local and CI environments.
|
|
32
32
|
|
|
33
|
-
**Target exactly the scope you need** - run by test
|
|
33
|
+
**Target exactly the scope you need** - run by test targets (`ace-test atoms`, `ace-test molecules`) or direct file/line selectors (`ace-test test/file_test.rb:42`) to focus on the code you are changing.
|
|
34
|
+
|
|
35
|
+
**Keep fast-loop defaults tight** - run `ace-test <package>` for `fast` coverage by default, then opt into `feat` when you need deterministic feature checks with controlled IO.
|
|
34
36
|
|
|
35
37
|
**Speed up triage on broken builds** - use failure-oriented output and persisted reports to locate regressions and continue diagnosis without rerunning broad suites.
|
|
36
38
|
|
|
37
|
-
**Validate the full monorepo before shipping** - run `ace-test-suite` for cross-package execution orchestration
|
|
39
|
+
**Validate the full monorepo before shipping** - run `ace-test-suite` for cross-package execution orchestration, and use `ace-test-e2e <package>` when you need scenario E2E coverage.
|
|
38
40
|
|
|
39
41
|
**Profile slow tests** - run `ace-test molecules --profile 10` to identify the slowest tests and prioritize optimization with [ace-test](../ace-test) performance audit workflows.
|
|
40
42
|
|
data/exe/ace-test-suite
CHANGED
|
@@ -38,6 +38,10 @@ parser = OptionParser.new do |opts|
|
|
|
38
38
|
options[:group] = group
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
opts.on("--target TARGET", "Pass target through to package-level ace-test (e.g. feat)") do |target|
|
|
42
|
+
options[:target] = target
|
|
43
|
+
end
|
|
44
|
+
|
|
41
45
|
opts.on("-t", "--timeout SEC", Integer, "Per-package timeout in seconds") do |timeout|
|
|
42
46
|
options[:timeout] = timeout
|
|
43
47
|
end
|
|
@@ -63,6 +67,7 @@ parser = OptionParser.new do |opts|
|
|
|
63
67
|
puts " $ ace-test-suite --parallel 16 Run with 16 parallel processes"
|
|
64
68
|
puts " $ ace-test-suite --timeout 10 Fail packages that run over 10s"
|
|
65
69
|
puts " $ ace-test-suite --group foundation Run only foundation group"
|
|
70
|
+
puts " $ ace-test-suite --target feat Run feat target in each package"
|
|
66
71
|
puts " $ ace-test-suite --verbose Show detailed test output"
|
|
67
72
|
exit 0
|
|
68
73
|
end
|
|
@@ -137,6 +142,11 @@ if options[:verbose]
|
|
|
137
142
|
config["test_suite"]["test_options"]["verbose"] = true
|
|
138
143
|
end
|
|
139
144
|
|
|
145
|
+
if options[:target]
|
|
146
|
+
config["test_suite"]["test_options"] ||= {}
|
|
147
|
+
config["test_suite"]["test_options"]["target"] = options[:target]
|
|
148
|
+
end
|
|
149
|
+
|
|
140
150
|
if options[:progress]
|
|
141
151
|
config["test_suite"]["progress"] = true
|
|
142
152
|
end
|
|
@@ -11,8 +11,8 @@ module Ace
|
|
|
11
11
|
# Returns the parent directory of the test folder + "/test-reports"
|
|
12
12
|
#
|
|
13
13
|
# Example:
|
|
14
|
-
# files = ["ace-
|
|
15
|
-
# detect_report_dir(files) # => "ace-
|
|
14
|
+
# files = ["ace-task/test/commands/tasks_command_test.rb"]
|
|
15
|
+
# detect_report_dir(files) # => "ace-task/test-reports"
|
|
16
16
|
def detect_report_dir(test_files)
|
|
17
17
|
return nil if test_files.nil? || test_files.empty?
|
|
18
18
|
|
|
@@ -31,8 +31,8 @@ module Ace
|
|
|
31
31
|
# Looks for "/test/" in the path and returns the path up to and including "test"
|
|
32
32
|
#
|
|
33
33
|
# Example:
|
|
34
|
-
# find_test_folder("ace-
|
|
35
|
-
# # => "ace-
|
|
34
|
+
# find_test_folder("ace-task/test/commands/tasks_command_test.rb")
|
|
35
|
+
# # => "ace-task/test"
|
|
36
36
|
def find_test_folder(file_path)
|
|
37
37
|
# Remove line number suffix if present (file:line format)
|
|
38
38
|
file_path = file_path.sub(/:\d+$/, "")
|
|
@@ -39,20 +39,24 @@ module Ace
|
|
|
39
39
|
# Check if explicitly marked as needing isolation
|
|
40
40
|
return true if isolation_directory?(file_path)
|
|
41
41
|
|
|
42
|
-
# Check
|
|
42
|
+
# Check file content for patterns that require subprocess
|
|
43
|
+
needs_isolation = check_file_content(file_path)
|
|
44
|
+
return true if needs_isolation
|
|
45
|
+
|
|
46
|
+
# Unit-directory tests default to in-process only when they do not
|
|
47
|
+
# exercise subprocess-sensitive behavior directly.
|
|
43
48
|
return false if unit_test_directory?(file_path)
|
|
44
49
|
|
|
45
|
-
|
|
46
|
-
check_file_content(file_path)
|
|
50
|
+
false
|
|
47
51
|
end
|
|
48
52
|
|
|
49
53
|
def test_type(file_path)
|
|
50
54
|
if isolation_directory?(file_path)
|
|
51
55
|
:integration
|
|
52
|
-
elsif unit_test_directory?(file_path)
|
|
53
|
-
:unit
|
|
54
56
|
elsif check_file_content(file_path)
|
|
55
57
|
:subprocess_required
|
|
58
|
+
elsif unit_test_directory?(file_path)
|
|
59
|
+
:unit
|
|
56
60
|
else
|
|
57
61
|
:unit
|
|
58
62
|
end
|
|
@@ -30,10 +30,9 @@ module Ace
|
|
|
30
30
|
molecules Run molecule tests only
|
|
31
31
|
organisms Run organism tests only
|
|
32
32
|
models Run model tests only
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
all Run all tests (default)
|
|
33
|
+
fast Run the default isolated fast loop
|
|
34
|
+
feat Run deterministic feature tests with controlled IO
|
|
35
|
+
all Run fast then feat
|
|
37
36
|
quick Run quick tests (atoms + molecules)
|
|
38
37
|
|
|
39
38
|
CONFIGURATION:
|
|
@@ -53,10 +52,10 @@ module Ace
|
|
|
53
52
|
ATOM Architecture Test Layers:
|
|
54
53
|
- atoms -> Pure functions (no side effects)
|
|
55
54
|
- molecules -> Composed operations (controlled side effects)
|
|
56
|
-
- organisms -> Business logic
|
|
55
|
+
- organisms -> Business logic with stubbed boundaries
|
|
57
56
|
- models -> Data structures (no behavior)
|
|
58
|
-
-
|
|
59
|
-
-
|
|
57
|
+
- fast -> Default isolated package test loop
|
|
58
|
+
- feat -> Deterministic feature coverage
|
|
60
59
|
DESC
|
|
61
60
|
|
|
62
61
|
# Examples shown in help output
|
|
@@ -79,7 +78,7 @@ module Ace
|
|
|
79
78
|
option :fail_fast, type: :boolean, desc: "Stop execution on first failure"
|
|
80
79
|
option :fix_deprecations, type: :boolean, desc: "Auto-fix deprecated test patterns"
|
|
81
80
|
option :filter, type: :string, desc: "Run only tests matching pattern"
|
|
82
|
-
option :
|
|
81
|
+
option :target, type: :string, aliases: %w[-g], desc: "Run specific test target (fast, feat, all)"
|
|
83
82
|
option :color, type: :boolean, desc: "Enable/disable colored output (default: enabled)"
|
|
84
83
|
option :config_path, type: :string, aliases: %w[-c], desc: "Configuration file path (default: .ace/test-runner.yml)"
|
|
85
84
|
|
|
@@ -93,7 +92,7 @@ module Ace
|
|
|
93
92
|
option :per_file, type: :boolean, desc: "Execute each test file separately (slower, for debugging)"
|
|
94
93
|
option :direct, type: :boolean, desc: "Force in-process execution (faster, less isolation)"
|
|
95
94
|
option :subprocess, type: :boolean, desc: "Force subprocess execution (slower, full isolation)"
|
|
96
|
-
option :run_in_sequence, type: :boolean, aliases: %w[--ris], desc: "Run test
|
|
95
|
+
option :run_in_sequence, type: :boolean, aliases: %w[--ris], desc: "Run test targets sequentially (default)"
|
|
97
96
|
option :run_in_single_batch, type: :boolean, aliases: %w[--risb], desc: "Run all tests together in single batch"
|
|
98
97
|
|
|
99
98
|
# Rake integration options
|
|
@@ -125,6 +124,10 @@ module Ace
|
|
|
125
124
|
options[key] = options[key].to_i if options[key]
|
|
126
125
|
end
|
|
127
126
|
|
|
127
|
+
if options[:target] && args.none? { |arg| !arg.start_with?("-") && !File.exist?(arg) }
|
|
128
|
+
args = [options[:target]] + args
|
|
129
|
+
end
|
|
130
|
+
|
|
128
131
|
# Build test options with defaults
|
|
129
132
|
test_options = build_test_options(options)
|
|
130
133
|
|
|
@@ -169,6 +172,7 @@ module Ace
|
|
|
169
172
|
end
|
|
170
173
|
# Remove the run_in_sequence key as it's only used to set run_in_single_batch
|
|
171
174
|
symbolized_options.delete(:run_in_sequence)
|
|
175
|
+
symbolized_options.delete(:target)
|
|
172
176
|
|
|
173
177
|
# Default options - symbolized_options will override these for any explicit values
|
|
174
178
|
{
|
|
@@ -185,15 +185,15 @@ module Ace
|
|
|
185
185
|
end
|
|
186
186
|
|
|
187
187
|
def on_test_complete(file, success, duration)
|
|
188
|
-
# Detect
|
|
189
|
-
|
|
188
|
+
# Detect target from file path
|
|
189
|
+
target = detect_target(file)
|
|
190
190
|
|
|
191
|
-
# Print
|
|
192
|
-
if @show_groups &&
|
|
191
|
+
# Print target header if it's a new target and target headers are enabled
|
|
192
|
+
if @show_groups && target != @current_group
|
|
193
193
|
puts unless @test_count == 0
|
|
194
194
|
puts ""
|
|
195
|
-
puts colorize("═══ #{
|
|
196
|
-
@current_group =
|
|
195
|
+
puts colorize("═══ #{target.to_s.capitalize} Tests ═══", :cyan)
|
|
196
|
+
@current_group = target
|
|
197
197
|
@test_count = 0 # Reset count for new line
|
|
198
198
|
end
|
|
199
199
|
|
|
@@ -207,47 +207,44 @@ module Ace
|
|
|
207
207
|
puts if @test_count % @line_width == 0
|
|
208
208
|
end
|
|
209
209
|
|
|
210
|
-
# Track
|
|
211
|
-
@group_counts[
|
|
210
|
+
# Track target counts
|
|
211
|
+
@group_counts[target] += 1 if @show_groups
|
|
212
212
|
end
|
|
213
213
|
|
|
214
|
-
def
|
|
214
|
+
def detect_target(file_path)
|
|
215
215
|
case file_path
|
|
216
|
-
when /test\/unit\/atoms\//
|
|
216
|
+
when /test\/(fast|unit)\/atoms\//
|
|
217
217
|
:atoms
|
|
218
|
-
when /test\/unit\/molecules\//
|
|
218
|
+
when /test\/(fast|unit)\/molecules\//
|
|
219
219
|
:molecules
|
|
220
|
-
when /test\/unit\/organisms\//
|
|
220
|
+
when /test\/(fast|unit)\/organisms\//
|
|
221
221
|
:organisms
|
|
222
|
-
when /test\/unit\/models\//
|
|
222
|
+
when /test\/(fast|unit)\/models\//
|
|
223
223
|
:models
|
|
224
|
-
when /test\/
|
|
225
|
-
:
|
|
226
|
-
when /test\/
|
|
227
|
-
:
|
|
224
|
+
when /test\/feat\//
|
|
225
|
+
:feat
|
|
226
|
+
when /test\/edge\//
|
|
227
|
+
:edge
|
|
228
228
|
else
|
|
229
229
|
:other
|
|
230
230
|
end
|
|
231
231
|
end
|
|
232
232
|
|
|
233
|
-
def
|
|
234
|
-
# Print visual separator before group
|
|
233
|
+
def on_target_start(target_name, file_count)
|
|
235
234
|
puts "" unless @test_count == 0
|
|
236
235
|
puts ""
|
|
237
|
-
puts "Running #{
|
|
236
|
+
puts "Running #{target_name} (#{file_count} #{(file_count == 1) ? "file" : "files"})..."
|
|
238
237
|
@test_count = 0
|
|
239
238
|
end
|
|
240
239
|
|
|
241
|
-
def
|
|
242
|
-
# Ensure we're on a new line after dots
|
|
240
|
+
def on_target_complete(target_name, success, duration, summary)
|
|
243
241
|
puts unless @test_count == 0 || @test_count % @line_width == 0
|
|
244
242
|
|
|
245
|
-
# Show group completion status
|
|
246
243
|
status_icon = success ? "✓" : "✗"
|
|
247
244
|
test_count = summary[:runs] || 0
|
|
248
245
|
failure_count = summary[:failures] || 0
|
|
249
246
|
|
|
250
|
-
status_line = "#{status_icon} #{
|
|
247
|
+
status_line = "#{status_icon} #{target_name} complete " +
|
|
251
248
|
"(#{format_duration(duration)}, #{test_count} tests, #{failure_count} failures)"
|
|
252
249
|
|
|
253
250
|
puts colorize(status_line, success ? :green : :red)
|
|
@@ -258,12 +255,12 @@ module Ace
|
|
|
258
255
|
# Ensure we're on a new line
|
|
259
256
|
puts unless @test_count == 0 || @test_count % @line_width == 0
|
|
260
257
|
|
|
261
|
-
# Print
|
|
258
|
+
# Print target summary if we have target headers enabled
|
|
262
259
|
if @show_groups && @group_counts.any?
|
|
263
260
|
puts ""
|
|
264
|
-
puts colorize("═══
|
|
265
|
-
@group_counts.each do |
|
|
266
|
-
puts " #{
|
|
261
|
+
puts colorize("═══ Target Summary ═══", :cyan)
|
|
262
|
+
@group_counts.each do |target, count|
|
|
263
|
+
puts " #{target.to_s.capitalize}: #{count} #{(count == 1) ? "file" : "files"}"
|
|
267
264
|
end
|
|
268
265
|
end
|
|
269
266
|
|
|
@@ -7,7 +7,7 @@ module Ace
|
|
|
7
7
|
class TestConfiguration
|
|
8
8
|
attr_accessor :format, :report_dir, :save_reports, :fail_fast,
|
|
9
9
|
:verbose, :filter, :fix_deprecations, :patterns,
|
|
10
|
-
:timeout, :parallel, :color, :per_file, :
|
|
10
|
+
:timeout, :parallel, :color, :per_file, :targets,
|
|
11
11
|
:target, :config_path, :failure_limits, :profile,
|
|
12
12
|
:execution, :files, :run_in_single_batch
|
|
13
13
|
|
|
@@ -20,13 +20,13 @@ module Ace
|
|
|
20
20
|
@filter = attributes[:filter]
|
|
21
21
|
@fix_deprecations = attributes[:fix_deprecations] || false
|
|
22
22
|
@patterns = attributes[:patterns] || default_patterns
|
|
23
|
-
@
|
|
23
|
+
@targets = attributes[:targets] || default_targets
|
|
24
24
|
@target = attributes[:target]
|
|
25
25
|
@config_path = attributes[:config_path]
|
|
26
26
|
@timeout = attributes[:timeout] # In seconds, nil = no timeout
|
|
27
27
|
@parallel = attributes[:parallel] || false
|
|
28
28
|
@color = attributes.fetch(:color, true)
|
|
29
|
-
@per_file = attributes[:per_file] || false # Default to
|
|
29
|
+
@per_file = attributes[:per_file] || false # Default to by-target execution for performance
|
|
30
30
|
@failure_limits = attributes[:failure_limits] || {max_display: 7}
|
|
31
31
|
@profile = attributes[:profile] # nil means no profiling, number means show N slowest tests
|
|
32
32
|
@execution = attributes[:execution] || {}
|
|
@@ -48,8 +48,8 @@ module Ace
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
# Validate execution_mode if provided
|
|
51
|
-
if execution_mode && !%w[
|
|
52
|
-
raise ArgumentError, "Unknown execution_mode '#{execution_mode}'. Valid modes:
|
|
51
|
+
if execution_mode && !%w[by-target all-at-once].include?(execution_mode)
|
|
52
|
+
raise ArgumentError, "Unknown execution_mode '#{execution_mode}'. Valid modes: by-target, all-at-once"
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
true
|
|
@@ -60,11 +60,11 @@ module Ace
|
|
|
60
60
|
@execution&.[](:mode) || @execution&.dig("mode") || "all-at-once"
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
def
|
|
64
|
-
# Default to true for better isolation in
|
|
63
|
+
def target_isolation
|
|
64
|
+
# Default to true for better isolation in by-target mode
|
|
65
65
|
# Use fetch to handle false values correctly (|| would treat false as falsy)
|
|
66
|
-
mode = @execution&.[](:
|
|
67
|
-
mode = @execution&.dig("
|
|
66
|
+
mode = @execution&.[](:target_isolation)
|
|
67
|
+
mode = @execution&.dig("target_isolation") if mode.nil?
|
|
68
68
|
mode.nil? || mode
|
|
69
69
|
end
|
|
70
70
|
|
|
@@ -83,7 +83,7 @@ module Ace
|
|
|
83
83
|
filter: filter,
|
|
84
84
|
fix_deprecations: fix_deprecations,
|
|
85
85
|
patterns: patterns,
|
|
86
|
-
|
|
86
|
+
targets: targets,
|
|
87
87
|
target: target,
|
|
88
88
|
config_path: config_path,
|
|
89
89
|
timeout: timeout,
|
|
@@ -125,20 +125,26 @@ module Ace
|
|
|
125
125
|
|
|
126
126
|
def default_patterns
|
|
127
127
|
{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
128
|
+
smoke: "test/{fast/,}*_test.rb",
|
|
129
|
+
atoms: "test/{fast/,}atoms/**/*_test.rb",
|
|
130
|
+
molecules: "test/{fast/,}molecules/**/*_test.rb",
|
|
131
|
+
organisms: "test/{fast/,}organisms/**/*_test.rb",
|
|
132
|
+
models: "test/{fast/,}models/**/*_test.rb",
|
|
133
|
+
commands: "test/{fast/,}commands/**/*_test.rb",
|
|
134
|
+
cli: "test/{fast/,}cli/**/*_test.rb",
|
|
135
|
+
prompts: "test/{fast/,}prompts/**/*_test.rb",
|
|
136
|
+
fixtures: "test/{fast/,}fixtures/**/*_test.rb",
|
|
137
|
+
support: "test/{fast/,}support/**/*_test.rb",
|
|
138
|
+
feat_tests: "test/feat/**/*_test.rb",
|
|
139
|
+
edge: "test/{fast/,}edge/**/*_test.rb"
|
|
135
140
|
}
|
|
136
141
|
end
|
|
137
142
|
|
|
138
|
-
def
|
|
143
|
+
def default_targets
|
|
139
144
|
{
|
|
140
|
-
|
|
141
|
-
|
|
145
|
+
fast: %w[smoke atoms molecules organisms models commands cli prompts fixtures support],
|
|
146
|
+
feat: %w[feat_tests edge],
|
|
147
|
+
all: %w[fast feat],
|
|
142
148
|
quick: %w[atoms molecules]
|
|
143
149
|
}
|
|
144
150
|
end
|