What changed
When tuist test builds an app for selective tests (the sharding .build flow) and a scheme resolved down to zero buildable test targets, the CLI failed with:
The scheme AllTests cannot be built because it contains no buildable targets.
Now, when testableTarget returns nil for the .build action — i.e. every testable target was excluded by selective testing cache hits or --skip-test-targets — the scheme is skipped (logged and bypassed) instead of throwing schemeWithoutTestableTargets. The command finishes successfully.
Why
A run that selective testing resolves to “no test targets to build” is a success, not a failure. On a PR where all touched test targets are cache hits, the user expects the command to finish cleanly rather than error out.
Root cause
testScheme unconditionally threw schemeWithoutTestableTargets when buildGraphInspector.testableTarget(...) returned nil. That nil is the legitimate outcome when target-level exclusions (testTargets / skipTestTargets) empty the scheme. For the .build action the right behavior is to skip that scheme and move on.
Why this approach over the alternative
The first iteration tried to detect the empty case earlier, inside shouldRunTest, by re-deriving the buildable target set from requestedTestTargets / skipTestTargets and matching against graph target names. That matching does not hold in the normal test flow, so shouldRunTest finished early for schemes that genuinely had targets to run, breaking ~13 existing TestServiceTests (caught by CI). Handling the empty case at its source — the single throw site — is both smaller and correct, and leaves the normal flow untouched.
Validation
- Added
test_skips_scheme_without_buildable_targets_for_build_action: with testableTarget resolving to nil under the .build action, the run completes without throwing and builds nothing. Verified red→green against the fix.
- Full
TuistKitTests/TestServiceTests suite passes (81 tests, 0 failures), confirming the earlier regression is gone.
How to test locally
- Generate and build:
tuist generate tuist TuistKit ProjectDescription TuistKitTests --no-open
- Run the suite:
xcodebuild test -workspace Tuist.xcworkspace -scheme Tuist-Workspace -only-testing TuistKitTests/TestServiceTests CODE_SIGNING_ALLOWED=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY=""