Skip to content

feat: add --related* flags to run affected tests only#765

Draft
stephanschubert wants to merge 4 commits intolunarmodules:masterfrom
stephanschubert:feat/related-tests
Draft

feat: add --related* flags to run affected tests only#765
stephanschubert wants to merge 4 commits intolunarmodules:masterfrom
stephanschubert:feat/related-tests

Conversation

@stephanschubert
Copy link
Copy Markdown

The --related option allows you to run only the tests that are affected by recent code changes. This is useful for faster feedback during development.

Basic Usage

Run tests related to uncommitted git changes:

busted --related

Run tests related to specific files (skips git, works anywhere):

busted --related-files=src/mymodule.lua,src/utils.lua

Compare against a specific git ref instead of HEAD:

busted --related --related-base=main

How It Works

  1. Detects changed files - Either from git (staged, unstaged, and untracked) or from an explicit file list
  2. Builds a dependency graph - Parses all Lua files to find require(), loadfile(), and dofile() statements
  3. Finds affected tests - Uses transitive closure to find all test files that depend on the changed files

Known Limitations

  • Dynamic requires are not detected - Calls like require(variable) or require("prefix" .. name) cannot be statically analyzed
  • External modules are ignored - Only project-local files are tracked in the dependency graph
  • Large files skipped - Files over 1MB are skipped to avoid performance issues (likely generated/minified code)

Performance Considerations

For large codebases:

  • First run may take a few seconds to build the dependency graph
  • Use --verbose to see dependency graph statistics
  • Consider using --related=files with explicit file lists for faster execution in CI

Add new --related, --related-files, and --related-base CLI options
that analyze code dependencies to run only tests affected by changes.

Includes:
- CLI argument parsing
- Runner integration
- busted/modules/related/ module suite
- Rockspec updates
- 43 unit tests for RequireParser, PathResolver, DependencyGraph, GitChanges
- 7 git integration tests with real temporary repos
- Mock-based tests for deterministic git behavior
- Test fixtures demonstrating dependency tracking
Add command context to error messages in git_changes for better debugging.
Add input validation for rootFiles/patterns parameters in init.lua.
Add optional verbose logging for parse failures in dependency_graph.
Fix assertion style in integration tests (assert.equals -> assert.are.equal).
@alerque
Copy link
Copy Markdown
Member

alerque commented Jan 23, 2026

No, we're not going to start requiring Git at runtime and hard coding assumptions about the VCS people are using. I realize Git is pretty ubiquitous at this point, but I've been through two major migrations in VCS in the past (CVS→Subversion and Subversion→Git) and there are new players these days like Jujitsu. Blinding noticing a .git directory and assuming you can figure out the differences between branches a certain way is not a good thing.

That's not to say that this isn't a useful feature for a test runner to accommodate, only that it needs to be architect ed differently. Busted as a test runner needs to accommodate receiving a list of tests somehow, then an external tool or plugin of some sort can be used to either call or as a callback to determine what to run based on VCS history. That's where this Git logic can be deployed.

I haven't thought about this enough to suggest whether a callback (runner asks something else what to run) or wrapper (something else figures out what to run and calls the runner) approach would be best, but I'm pretty confident the direct approach with CLI flags hard coded to a certain Git VCS layout is not something I'm willing to include.

@alerque alerque marked this pull request as draft January 23, 2026 12:07
Comment thread busted/modules/cli.lua
cli:flag('--[no-]sort-tests', 'sort test order within a file', processOption)
cli:flag('--[no-]suppress-pending', 'suppress `pending` test output', false, processOption)
cli:flag('--[no-]defer-print', 'defer print to when test suite is complete', false, processOption)
cli:flag('--related', 'only run tests related to uncommitted git changes. Note: dynamic requires like require(var) are not detected.', false, processOption)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functionality directly baked into Busted should never assume Git is the VCS in charge.

@Tieske
Copy link
Copy Markdown
Member

Tieske commented Jan 25, 2026

iirc @eskerda added some extension mechanism I while back

@Tieske
Copy link
Copy Markdown
Member

Tieske commented Jan 25, 2026

this PR #658 (haven't checked whether it handles this use case)

@stephanschubert
Copy link
Copy Markdown
Author

@Tieske @alerque Thanks for the feedback, I'll take a look

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants