XCTestHTMLReport/CONTRIBUTING.md at main · XCTestHTMLReport/XCTestHTMLReport · GitHub
Skip to content

Latest commit

 

History

History
155 lines (112 loc) · 6.28 KB

CONTRIBUTING.md

File metadata and controls

155 lines (112 loc) · 6.28 KB

Contributing Guidelines

This document contains information and guidelines about contributing to this project. Please read it before you start participating.

Topics

Reporting Issues

A great way to contribute to the project is to send a detailed issue when you encounter an problem. I always appreciate a well-written, thorough bug report.

Check that the project issues database doesn't already include that problem or suggestion before submitting an issue. If you find a match, add a quick "+1" or "I have this problem too." Doing this helps prioritize the most common problems and requests.

When reporting issues, please include the following:

  • The version of Xcode you're using
  • The version of iOS or OS X you're targeting
  • The full output of the command
  • An archive of the resultBundlePath (Whenever possible)
  • Any other details that would be useful in understanding the problem

This information will help review and fix your issue faster.

Create an issue

Submitting Pull Requests

Pull requests are welcome, and greatly encouraged. When submitting a pull request, please add a description that explains what the changes are about. Link the ticket whenever possible.

  • As usual, anyone can clone the repository. Then do the fixes/improvements as needed in own repository. When it is finished you can start the request to pull code from your own repo to XCTestHTMLReport repo.

Building and testing

The Swift test suite runs against real .xcresult bundles. Generate them once, then run the tests:

./prepareTestResults.sh   # builds the sample app and produces fixtures
swift test

prepareTestResults.sh picks the newest available iPhone simulator automatically. No credentials or secrets are required for this part.

If a simulator goes away mid-run, xcodebuild can leave an .xcresult behind that looks complete but holds no tests, and the suite then fails with a confusing error. A host-app launch failure does something subtler: the bundle is full of tests, just not the ones hosted in the app. scripts/verify_fixtures.sh — the same gate CI runs — catches both in a second:

./scripts/verify_fixtures.sh   # asserts each bundle holds its expected test count

It knows the shape of each fixture (21, 1 and 4 tests for the three healthy ones), so a bundle that generated partially is rejected by name and count rather than waved through. Adding or removing sample-app tests moves those numbers: update the table at the top of the script in the same commit.

The fourth bundle, CrashResults.xcresult, is a broken run on purpose: the script sets XCHR_TRAP_AT_LAUNCH, the sample app traps in didFinishLaunchingWithOptions, and SampleAppUnitTests — hosted in that app — dies with it. SystemFailureCanaryTests reads it to check that Apple still calls the resulting group System Failures, which is the only handle the systemFailure fault has. Expect one failing xcodebuild invocation during generation; that is the fixture being made, not a problem.

Regenerate fixtures after upgrading Xcode; .xcresult contents change between Xcode versions.

swift test also runs two other layers that need no .xcresult and no simulator, because they render from a hand-written synthetic fixture instead:

  • Template snapshots — TemplateSnapshotTests compares rendered HTML against committed goldens in Tests/XCTestHTMLReportTests/Snapshots/. If a template change is intentional, refresh the goldens and review the diff before committing:

    XCHR_UPDATE_SNAPSHOTS=1 swift test --filter TemplateSnapshotTests

    A refresh run always fails on purpose (SnapshotSupport.swift) — writing a golden proves nothing about whether the new content is correct. Re-run without the environment variable afterwards to get a real verdict.

  • Browser assertions — visual/ at the repository root is a separate npm project (Playwright + axe-core) checking things only a browser knows: computed token values, WCAG contrast in light and dark mode, accessibility violations, and interactive behaviour. It reads a report file rather than building one, so first dump the synthetic fixture:

    XCHR_VISUAL_DIR="$(pwd)/visual/fixtures" swift test --filter VisualFixtureDumpTests
    cd visual
    npm ci
    npx playwright test

    CI runs this as two jobs, mirrored above: a macOS job dumps the fixture, an ubuntu job installs Playwright's browsers and runs the assertions against it. See docs/superpowers/specs/2026-08-13-report-visual-test-coverage-design.md for the full design and its layers.

CI runs prepareTestResults.sh, swift test, and the visual/ job above, so a green run of all of it locally means a green run on your pull request.

Optional: run the checks before committing

CI runs shellcheck, SwiftFormat, and SwiftLint. The same checks can run locally on staged files, so you find problems before pushing.

mise installs the versions pinned in mise.toml — the same ones CI uses, so a linter release cannot fail your pull request on a file you did not touch — and, as a side effect, the pre-commit hook itself:

brew install mise            # or https://mise.jdx.dev/installing-mise.html
mise trust && mise install

That is opt-in on purpose: nothing installs it for you, and mise trust is where you agree to let the repository run its own setup.

The same file indexes the repository's runnable scripts: mise tasks lists them (fixture generation and both comparison harnesses), and mise run <task> -- <flags> runs one with its flags passed through.

The hook is defined in hk.pkl. It only checks files you are actually committing, and reports problems rather than rewriting your files, so a commit never contains changes you have not read. To skip it for one commit:

git commit --no-verify

If you set up the older .githooks directory, it is gone now, and the core.hooksPath it left behind will stop the new hook from firing. Clear it once:

git config --local --unset-all core.hooksPath

*Some of the ideas and wording for the statements above were based on AFNetworking.