Developer-Dashboard
view release on metacpan or search on metacpan
doc/testing.md view on Meta::CPAN
# Testing
## Test Suite
Run the full test suite with:
```bash
prove -lr t
```
The dotted installed-skill command regressions cover both `cli/<command>.py`
and `cli/<command>.js`. The JavaScript execution assertions require `node` on
`PATH`, so the release tarball gate keeps the path-resolution assertions
everywhere and skips only the `.js` execution step on minimal hosts that do not
ship Node.js.
Collector lifecycle regressions also cover two macOS-specific runtime rules:
Dashboard-owned Perl child processes must keep the current interpreter ahead of
the system Perl in `PATH`, and collector shell commands must avoid login-shell
startup chatter that can prepend text ahead of collector JSON output.
Those path regressions now also lock in the shell side of that contract:
dashboard-managed child commands must keep the active shell directory in
`PATH`, not just the Perl interpreter bin, because `_run_command` executes
shell collectors through `sh -c` and blank-environment install verification
will fail if `perl` is found but `sh` is not.
Run the fast saved-bookmark browser smoke check with:
```bash
integration/browser/run-bookmark-browser-smoke.pl
```
That host-side smoke runner creates an isolated temporary runtime, starts the
checkout-local dashboard, loads one saved bookmark page through headless
Chromium, and can assert page-source fragments, saved `/ajax/...` output, and
the final browser DOM. With no arguments it runs the built-in Ajax
`foo.bar` bookmark case.
For a real bookmark file, point it at the saved file and add the specific
browser assertions you care about:
```bash
integration/browser/run-bookmark-browser-smoke.pl \
--bookmark-file ~/.developer-dashboard/dashboards/test \
--expect-page-fragment "set_chain_value(foo,'bar','/ajax/foobar?type=text')" \
--expect-ajax-path /ajax/foobar?type=text \
--expect-ajax-body 123 \
--expect-dom-fragment '<span class="display">123</span>'
```
For a skill page that declares `config/routes.json`, assert the canonical
custom ajax path rather than the default smart `/ajax/<repo-name>/...` path:
```bash
integration/browser/run-bookmark-browser-smoke.pl \
--bookmark-file ~/.developer-dashboard/skills/example-skill/dashboards/index \
--expect-page-fragment "set_chain_value(endpoints,'status','/v1/status')" \
--expect-ajax-path /v1/status \
--expect-ajax-body '{"status":"ok"}'
```
For long-running saved bookmark Ajax handlers that would otherwise survive a
browser refresh, prefer `Ajax(..., singleton => 'NAME', ...)`. The runtime will
rename the Perl worker to `dashboard ajax: NAME`, terminate the older matching
Perl stream before it starts the refreshed one, and also tear down matching
singleton workers during `dashboard stop`, `dashboard restart`, and browser
`pagehide` cleanup beacons. For browser streaming checks, use `stream_data()`
or `stream_value()` against a finite saved Ajax handler and assert the final
DOM after incremental chunks land.
## Coverage
Install Devel::Cover in a local Perl library and generate the coverage report:
```bash
cpanm --notest --local-lib-contained ./.perl5 Devel::Cover
export PERL5LIB="$PWD/.perl5/lib/perl5${PERL5LIB:+:$PERL5LIB}"
export PATH="$PWD/.perl5/bin:$PATH"
cover -delete
HARNESS_PERL_SWITCHES=-MDevel::Cover prove -lr t
PERL5OPT=-MDevel::Cover prove -lr t
cover -report text -select_re '^lib/' -coverage statement -coverage subroutine
```
Developer Dashboard expects a reviewed `lib/` coverage report before release, and the current repository target is 100% statement and subroutine coverage for `lib/`.
This is a standing QA gate for every change, not only releases. After the
normal `prove -lr t` test gate passes, run the numeric `Devel::Cover` gate and
do not treat the work as done until the `cover` summary still reports 100%
statement and 100% subroutine coverage for `lib/`.
The coverage-closure suite includes managed collector loop start/stop paths under `Devel::Cover`, including wrapped fork coverage in `t/14-coverage-closure-extra.t`, so the covered run stays green without breaking TAP from daemon-style child processe...
Managed collector children now scrub inherited `PERL5OPT` and `HARNESS_PERL_SWITCHES` coverage settings before their long-lived loop work begins, and the runtime manager widens its startup stability polls when the parent harness is running under `Dev...
The collector stop path is also part of that regression surface now: a managed
loop must be truly gone before its pid/state files are cleaned up, otherwise a
dying old loop can keep rewriting state while a replacement restart is trying
to prove its new pid. `t/07-core-units.t`, `t/09-runtime-manager.t`, and the
covered `t/05-cli-smoke.t` restart/serve flows now lock that race down.
The runtime child-lifecycle contract is also part of the regression surface now: collector stop paths, collector loop parents, watchdog shutdown, detached background actions, and the SSL frontend must reap the direct children they own so macOS, Linux...
Collector scheduler coverage now also locks in the overlap policy contract:
default collector mode is singleton, opt-in `mode => multiple` collectors can
overlap only up to their `multiple` bound, and concurrent worker completion
must keep `active_runs` plus `running` status accurate under lock.
The live singleton regression now also proves that a real long-running command
still holds the single active worker slot across multiple due ticks, and that
stopping the collector loop tears down that long-running command instead of
only stopping the loop wrapper.
Collector disable coverage now also locks in the stop-and-skip contract:
`disable => 1` collectors are not started, explicit named starts reject them,
already-running managed loops for those collectors are stopped on the next
lifecycle action, and managed collector indicators are removed instead of
staying behind as stale active state.
GitHub workflow coverage gates must match the `Devel::Cover` `Total` summary
line by regex rather than one fixed-width spacing layout, because runner or
module upgrades can change column padding without changing the real
`100.0 / 100.0 / 100.0` result.
The `t/07-core-units.t` collector loop guard treats both `HARNESS_PERL_SWITCHES` and `PERL5OPT` as valid `Devel::Cover` signals, because this machine uses both launch styles during verification.
( run in 1.044 second using v1.01-cache-2.11-cpan-524268b4103 )