Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
2026-10-29 Daniel Boyd <danieljboyd@icloud.com>

* XCode/PBXProject+Testing.[hm]: New. `buildtool test`: build the
project, then run each unit-test target's bundle with xctest
(tools-xctest), selected with -target, a scheme's testables and
skipped/selected tests, or xcodebuild's -only-testing/-skip-testing.
A target whose TEST_HOST names an application in the project runs
inside it (xctest -host).
* XCode/PBXContainer.[hm] (setTestOptions:, test): New.
* XCode/GNUmakefile: Add PBXProject+Testing.[hm].
* XCode/PBXProject+Testing.m: -only-testing becomes xctest's -XCTest
selection; skipped tests and TEST_HOST use xctest's -skip-testing and
-host only when its --help lists them, and fail with a message
otherwise.
* Tools/buildtool/ToolDelegate.m (testOptions:): New. Add the test
action; for it, -target and -scheme choose the test targets instead
of narrowing the build, so test hosts are still built.
* Tests/Fixtures/Xcode/unit-tests, Tests/run-buildtool-test-action.sh:
New. A project with unit tests, an application and hosted tests, and
regressions for `buildtool test`.
* README.md: Document `buildtool test`.

2026-01-10 Gregory John Casamento <greg.casamento@gmail.com>

* XCode/PBXNativeTarget.m: Include TEST_TYPE in bundle-style
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,31 @@ Supported xcodebuild-style options:
`-parallelizeTargets`, `-quiet`, `-verbose`, `-list`, and
`-showBuildSettings` are accepted for command-line compatibility.

`buildtool test` builds the project, like `xcodebuild test`, then runs each
unit-test target's `.xctest` bundle with `xctest` from
[tools-xctest](https://github.com/gnustep/tools-xctest). For `test`,
`-target` and `-scheme` choose the test targets (a scheme's testables and
its skipped or selected tests) rather than narrowing the build, so test
hosts are still built:

```
buildtool test # every unit-test target
buildtool test -target MyTests # one target
buildtool test -scheme MyApp # a scheme's testables
buildtool test -only-testing:MyTests/FooTests -skip-testing:MyTests/FooTests/testSlow
```

`-only-testing:` becomes an `-XCTest` selection, which any tools-xctest
accepts. Skipping tests (`-skip-testing:`, or a scheme's skipped tests) needs
an `xctest` that lists `-skip-testing` in its `--help`, and a test target
whose `TEST_HOST` names an application in the project runs inside that
application, which needs one that lists `-host` (and an X display, e.g.
`xvfb-run -a buildtool test`). With an older `xctest`, those targets fail
with a message saying so. `XCTEST` chooses the `xctest` program, and
`XCTEST_FLAGS` passes extra options to it (e.g.
`XCTEST_FLAGS="-junit-report results.xml"`). buildtool exits with status 1
when the build or any test fails.

Buildtool exits with status 0 on success and nonzero on a failed operation,
invalid project path, or exception. An explicit project path never falls back
to another project in the current directory.
Expand Down
8 changes: 8 additions & 0 deletions Tests/Fixtures/Xcode/unit-tests/App/AppDelegate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#import <AppKit/AppKit.h>

@interface AppDelegate : NSObject
{
BOOL launched;
}
@property BOOL launched;
@end
10 changes: 10 additions & 0 deletions Tests/Fixtures/Xcode/unit-tests/App/AppDelegate.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#import "AppDelegate.h"

@implementation AppDelegate
@synthesize launched;

- (void) applicationDidFinishLaunching: (NSNotification *)notification
{
[self setLaunched: YES];
}
@end
10 changes: 10 additions & 0 deletions Tests/Fixtures/Xcode/unit-tests/App/main.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#import <AppKit/AppKit.h>
#import "AppDelegate.h"

int main(int argc, const char *argv[])
{
NSApplication *app = [NSApplication sharedApplication];
[app setDelegate: [[AppDelegate alloc] init]];
[app run];
return 0;
}
16 changes: 16 additions & 0 deletions Tests/Fixtures/Xcode/unit-tests/AppTests/AppTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#import <AppKit/AppKit.h>
#import <XCTest/XCTest.h>

@interface AppTests : XCTestCase
@end

@implementation AppTests

- (void) testRunsInsideTheApp
{
XCTAssertNotNil(NSApp);
XCTAssertEqualObjects(NSStringFromClass([[NSApp delegate] class]), @"AppDelegate");
XCTAssertEqualObjects([(NSObject *)[NSApp delegate] valueForKey: @"launched"], [NSNumber numberWithBool: YES]);
}

@end
Loading
Loading