Skip to content

Commit

Permalink
Merge pull request #166 from linkedin/fix-165
Browse files Browse the repository at this point in the history
Fixed a bug that skipped tests in BPXCTestFile not picked up #165
  • Loading branch information
oliverhu authored Jun 20, 2017
2 parents ce998c3 + 0e061a7 commit a562c97
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 139 deletions.
2 changes: 1 addition & 1 deletion Bluepill-runner/Bluepill-runner/BPApp.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@interface BPApp : NSObject

// All test bundles inside PlugIns directory in app.
@property (nonatomic, strong) NSArray *testBundles;
@property (nonatomic, strong) NSArray<BPXCTestFile *> *testBundles;

+ (instancetype)appWithConfig:(BPConfiguration *)config
withError:(NSError **)error;
Expand Down
2 changes: 2 additions & 0 deletions Bluepill-runner/Bluepill-runner/BPPacker.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ @implementation BPPacker
range.length = min(testsPerGroup, bundleTestsToRun.count - packed);
NSMutableArray *testsToSkip = [NSMutableArray arrayWithArray:allTestCases];
[testsToSkip removeObjectsInArray:[bundleTestsToRun subarrayWithRange:range]];
[testsToSkip addObjectsFromArray:xctFile.skipTestIdentifiers];
[testsToSkip sortUsingSelector:@selector(compare:)];
BPXCTestFile *bundle = [xctFile copy];
bundle.skipTestIdentifiers = testsToSkip;
[bundles addObject:bundle];
Expand Down
4 changes: 4 additions & 0 deletions Bluepill-runner/Bluepill.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
BA1809FB1DBA949600D7D130 /* BPPacker.m in Sources */ = {isa = PBXBuildFile; fileRef = C4FD8C571DB6E09B000ED28C /* BPPacker.m */; };
BA1809FD1DBA949600D7D130 /* BPApp.m in Sources */ = {isa = PBXBuildFile; fileRef = C41C41F21DB04032001F32A2 /* BPApp.m */; };
BA180A021DBA949600D7D130 /* BPUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = C4FD8C5D1DB80971000ED28C /* BPUtils.m */; };
BA23EF611EF8ACF10074A4EF /* BPPackerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = BA23EF601EF8ACF10074A4EF /* BPPackerTests.m */; };
BA53B16F1E30932400FCED71 /* BPConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = BA53B16E1E30932400FCED71 /* BPConstants.m */; };
BA7031881DE4ED2F008B3539 /* result1.xml in Resources */ = {isa = PBXBuildFile; fileRef = BA7031831DE4ED2F008B3539 /* result1.xml */; };
BA7031891DE4ED2F008B3539 /* result2.xml in Resources */ = {isa = PBXBuildFile; fileRef = BA7031851DE4ED2F008B3539 /* result2.xml */; };
Expand Down Expand Up @@ -67,6 +68,7 @@
BA1809EA1DBA910400D7D130 /* BPAppTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BPAppTests.m; sourceTree = "<group>"; };
BA1809EC1DBA929600D7D130 /* BPTestHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BPTestHelper.h; path = "../../Bluepill-cli/BPInstanceTests/BPTestHelper.h"; sourceTree = "<group>"; };
BA1809ED1DBA929600D7D130 /* BPTestHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BPTestHelper.m; path = "../../Bluepill-cli/BPInstanceTests/BPTestHelper.m"; sourceTree = "<group>"; };
BA23EF601EF8ACF10074A4EF /* BPPackerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BPPackerTests.m; sourceTree = "<group>"; };
BA53B16D1E30932400FCED71 /* BPConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BPConstants.h; sourceTree = "<group>"; };
BA53B16E1E30932400FCED71 /* BPConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BPConstants.m; sourceTree = "<group>"; };
BA7031831DE4ED2F008B3539 /* result1.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = result1.xml; sourceTree = "<group>"; };
Expand Down Expand Up @@ -145,6 +147,7 @@
BAD8484C1DBC6BA2007034CF /* BPReportCollectorTests.m */,
C467E54B1DC94BB200BC80EE /* BPCLITests.m */,
56B74BC91E4C0A15004E6624 /* BPIntegrationTests.m */,
BA23EF601EF8ACF10074A4EF /* BPPackerTests.m */,
);
path = BluepillRunnerTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -359,6 +362,7 @@
BA180A021DBA949600D7D130 /* BPUtils.m in Sources */,
BA1809EE1DBA929600D7D130 /* BPTestHelper.m in Sources */,
7A6672C11E0B0BBC00AC6778 /* BPTestClass.m in Sources */,
BA23EF611EF8ACF10074A4EF /* BPPackerTests.m in Sources */,
56B74BCA1E4C0A15004E6624 /* BPIntegrationTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
2 changes: 2 additions & 0 deletions Bluepill-runner/BluepillRunnerTests/BPIntegrationTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,12 @@ - (void)testTwoBPInstancesWithXCTestRunFile {
NSString *xcTestRunFile = [NSString stringWithFormat:@"BPSampleApp_iphonesimulator%@-x86_64.xctestrun", runtime];
self.config.xcTestRunPath = [[[BPTestHelper derivedDataPath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:xcTestRunFile];
NSError *err;
[self.config validateConfigWithError:&err];
BPApp *app = [BPApp appWithConfig:self.config withError:&err];
NSString *bpPath = [BPTestHelper bpExecutablePath];
BPRunner *runner = [BPRunner BPRunnerWithConfig:self.config withBpPath:bpPath];
int rc = [runner runWithBPXCTestFiles:app.testBundles];
XCTAssert(app.testBundles[1].skipTestIdentifiers.count == 7);
XCTAssert(rc != 0); // this runs tests that fail

}
Expand Down
208 changes: 208 additions & 0 deletions Bluepill-runner/BluepillRunnerTests/BPPackerTests.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
//
// BPPackerTests.m
// Bluepill
//
// Created by Keqiu Hu on 6/19/17.
// Copyright © 2017 LinkedIn. All rights reserved.
//

#import <XCTest/XCTest.h>
#import "BPTestHelper.h"
#import "BPConfiguration.h"
#import "BPUtils.h"
#import "BPRunner.h"
#import "BPApp.h"
#import "BPPacker.h"
#import "BPXCTestFile.h"
#import "BPConstants.h"

@interface BPPackerTests : XCTestCase
@property (nonatomic, strong) BPConfiguration* config;
@end

@implementation BPPackerTests

- (void)setUp {
[super setUp];

NSString *hostApplicationPath = [BPTestHelper sampleAppPath];
NSString *testBundlePath = [BPTestHelper sampleAppNegativeTestsBundlePath];
self.config = [BPConfiguration new];
self.config.program = BP_MASTER;
self.config.testBundlePath = testBundlePath;
self.config.appBundlePath = hostApplicationPath;
self.config.stuckTimeout = @30;
self.config.xcodePath = [BPUtils runShell:@"/usr/bin/xcode-select -print-path"];
self.config.runtime = @BP_DEFAULT_RUNTIME;
self.config.repeatTestsCount = @1;
self.config.errorRetriesCount = @0;
self.config.failureTolerance = @0;
self.config.deviceType = @BP_DEFAULT_DEVICE_TYPE;
self.config.plainOutput = NO;
self.config.jsonOutput = NO;
self.config.headlessMode = NO;
self.config.junitOutput = NO;
NSString *path = @"testScheme.xcscheme";
self.config.schemePath = [[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingPathComponent:path];
}

- (void)tearDown {
self.config.testCasesToSkip = @[];
[super tearDown];
}

- (void)testPackingWithXctFileContainingSkipTestIdentifiers {
self.config.testBundlePath = [BPTestHelper sampleAppBalancingTestsBundlePath];
self.config.numSims = @2;
BPApp *app = [BPApp appWithConfig:self.config withError:nil];
NSMutableArray *testCasesToSkip = [NSMutableArray new];
app.testBundles[0].skipTestIdentifiers = @[@"BPSampleAppTests/testCase000", @"BPSampleAppTests/testCase001"];

XCTAssert(app != nil);
NSArray<BPXCTestFile *> *bundles;
bundles = [BPPacker packTests:app.testBundles configuration:self.config andError:nil];
for (BPXCTestFile *file in app.testBundles) {
XCTAssert([file.skipTestIdentifiers containsObject: @"BPSampleAppTests/testCase000"]);
XCTAssert([file.skipTestIdentifiers containsObject: @"BPSampleAppTests/testCase001"]);
}
}

- (void)testPackingProvidesBalancedBundles {
self.config.testBundlePath = [BPTestHelper sampleAppBalancingTestsBundlePath];
self.config.numSims = @8;
BPApp *app = [BPApp appWithConfig:self.config withError:nil];
NSMutableArray *testCasesToSkip = [NSMutableArray new];
for (BPXCTestFile *xctFile in app.testBundles) {
[testCasesToSkip addObjectsFromArray:xctFile.allTestCases];
}
for (long i = 1; i <= 8; i++) {
[testCasesToSkip removeObject:[NSString stringWithFormat:@"BPSampleAppTests/testCase%03ld", i]];
}
self.config.testCasesToSkip = testCasesToSkip;
XCTAssert(app != nil);
NSArray<BPXCTestFile *> *bundles;
bundles = [BPPacker packTests:app.testBundles configuration:self.config andError:nil];
for (long i = 1; i <= 8; i++) {
BPXCTestFile *bpBundle = bundles[i - 1];
NSString *testThatShouldExist = [NSString stringWithFormat:@"BPSampleAppTests/testCase%03ld", i];
XCTAssertFalse([bpBundle.skipTestIdentifiers containsObject:testThatShouldExist]);
}
}

- (void)testPacking {
NSArray *want, *got;
NSArray *allTests;
NSArray<BPXCTestFile *> *bundles;

allTests = [[NSMutableArray alloc] init];
self.config.testBundlePath = nil;
BPApp *app = [BPApp appWithConfig:self.config withError:nil];
XCTAssert(app != nil);
// Make sure we have the test bundles we expect. If we add more, this will pop but that's okay. Just add
// the additional test bundles here.
want = @[ @"BPAppNegativeTests.xctest",
@"BPSampleAppCrashingTests.xctest",
@"BPSampleAppFatalErrorTests.xctest",
@"BPSampleAppHangingTests.xctest",
@"BPSampleAppTests.xctest"];
NSMutableArray *tests = [[NSMutableArray alloc] init];
for (BPXCTestFile *bundle in app.testBundles) {
[tests addObject:[bundle.testBundlePath lastPathComponent]];
}
got = [tests sortedArrayUsingSelector:@selector(compare:)];
XCTAssert([want isEqualToArray:got]);

// Let's gather all the tests and always make sure we get them all
tests = [[NSMutableArray alloc] init];
for (BPXCTestFile *testFile in app.testBundles) {
[tests addObjectsFromArray:[testFile allTestCases]];
}
allTests = [tests sortedArrayUsingSelector:@selector(compare:)];
// Make sure we don't split when we don't want to
self.config.numSims = @4;
self.config.noSplit = @[@"BPSampleAppTests"];
bundles = [BPPacker packTests:app.testBundles configuration:self.config andError:nil];// withNoSplitList:@[@"BPSampleAppTests"] intoBundles:4 andError:nil];
// When we prevent BPSampleTests from splitting, BPSampleAppFatalErrorTests gets split in two
want = [[want arrayByAddingObject:@"BPSampleAppFatalErrorTests"] sortedArrayUsingSelector:@selector(compare:)];
XCTAssert(bundles.count == app.testBundles.count + 1);

XCTAssert([bundles[0].skipTestIdentifiers count] == 0);
XCTAssert([bundles[1].skipTestIdentifiers count] == 0);
XCTAssert([bundles[2].skipTestIdentifiers count] == 0);
XCTAssert([bundles[3].skipTestIdentifiers count] == 0);
XCTAssert([bundles[4].skipTestIdentifiers count] == 2);
XCTAssert([bundles[5].skipTestIdentifiers count] == 3);

self.config.numSims = @4;
self.config.noSplit = nil;
bundles = [BPPacker packTests:app.testBundles configuration:self.config andError:nil];
// 4 unbreakable bundles (too few tests) and the big one broken into 4 bundles
XCTAssert(bundles.count == 8);
// All we want to test is that we have full coverage
XCTAssert([bundles[0].skipTestIdentifiers count] == 0);
XCTAssert([bundles[1].skipTestIdentifiers count] == 0);
XCTAssert([bundles[2].skipTestIdentifiers count] == 0);
XCTAssert([bundles[3].skipTestIdentifiers count] == 0);
XCTAssert([bundles[4].skipTestIdentifiers count] == 148);
XCTAssert([bundles[5].skipTestIdentifiers count] == 148);
XCTAssert([bundles[6].skipTestIdentifiers count] == 148);
XCTAssert([bundles[7].skipTestIdentifiers count] == 159);

self.config.numSims = @1;
bundles = [BPPacker packTests:app.testBundles configuration:self.config andError:nil];
// If we pack into just one bundle, we can't have less bundles than the total number of .xctest files.
XCTAssert(bundles.count == app.testBundles.count);

self.config.numSims = @16;
bundles = [BPPacker packTests:app.testBundles configuration:self.config andError:nil];

XCTAssert([bundles[0].skipTestIdentifiers count] == 0);
XCTAssert([bundles[1].skipTestIdentifiers count] == 0);
XCTAssert([bundles[2].skipTestIdentifiers count] == 0);
XCTAssert([bundles[3].skipTestIdentifiers count] == 0);
XCTAssert([bundles[4].skipTestIdentifiers count] == 188);
XCTAssert([bundles[5].skipTestIdentifiers count] == 188);
XCTAssert([bundles[6].skipTestIdentifiers count] == 188);
XCTAssert([bundles[7].skipTestIdentifiers count] == 188);
XCTAssert([bundles[8].skipTestIdentifiers count] == 188);
XCTAssert([bundles[9].skipTestIdentifiers count] == 188);
XCTAssert([bundles[10].skipTestIdentifiers count] == 188);
XCTAssert([bundles[11].skipTestIdentifiers count] == 188);
XCTAssert([bundles[12].skipTestIdentifiers count] == 188);
XCTAssert([bundles[13].skipTestIdentifiers count] == 188);
XCTAssert([bundles[14].skipTestIdentifiers count] == 188);
XCTAssert([bundles[15].skipTestIdentifiers count] == 188);
XCTAssert([bundles[16].skipTestIdentifiers count] == 188);
XCTAssert([bundles[17].skipTestIdentifiers count] == 188);
XCTAssert([bundles[18].skipTestIdentifiers count] == 188);
XCTAssert([bundles[19].skipTestIdentifiers count] == 195);

NSMutableArray *toRun = [[NSMutableArray alloc] init];
for (long i = 1; i <= 20; i++) {
[toRun addObject:[NSString stringWithFormat:@"BPSampleAppTests/testCase%03ld", i]];
}
self.config.numSims = @4;
self.config.testCasesToRun = toRun;
bundles = [BPPacker packTests:app.testBundles configuration:self.config andError:nil];

XCTAssertEqual(bundles.count, 4);
for (BPXCTestFile *bundle in bundles) {
XCTAssertEqual(bundle.skipTestIdentifiers.count, 196);
}
}

- (void)testPackingWithTestsToSkip {
self.config.testBundlePath = [BPTestHelper sampleAppBalancingTestsBundlePath];
self.config.testCasesToSkip = @[@"BPSampleAppTests/testCase000"];
self.config.numSims = @8;
BPApp *app = [BPApp appWithConfig:self.config withError:nil];
XCTAssert(app != nil);
NSArray<BPXCTestFile *> *bundles;
bundles = [BPPacker packTests:app.testBundles configuration:self.config andError:nil];
for (BPXCTestFile *bundle in bundles) {
XCTAssertTrue([bundle.skipTestIdentifiers containsObject:@"BPSampleAppTests/testCase000"], @"testCase000 should be in testToSkip for all bundles");
}

}

@end
Loading

0 comments on commit a562c97

Please sign in to comment.