Removed need for XCTStubApp for simulators

Summary:We can kick off test bundle from any application so instead of forcing creating own application for that added posiibility to start test with any bundle id (our own app, or existing apple apps).

Unfortunately devices are more tricky so, this is simulator solution for now.

Reviewed By: lawrencelomax

Differential Revision: D3120820

fb-gh-sync-id: 712197ea41624947b50527c9b4db8aa8703418d0
fbshipit-source-id: 712197ea41624947b50527c9b4db8aa8703418d0
This commit is contained in:
Marek Cirkos 2016-04-01 03:29:51 -07:00 коммит произвёл Facebook Github Bot 8
Родитель f505213050
Коммит 9b97af33e2
11 изменённых файлов: 116 добавлений и 60 удалений

Просмотреть файл

@ -13,6 +13,8 @@
#import <IDEiOSSupportCore/DVTiPhoneSimulator.h>
#import <XCTestBootstrap/FBProductBundle.h>
@interface FBSimulatorControlOperator ()
@property (nonatomic, strong) DVTiPhoneSimulator *dvtDevice;
@property (nonatomic, strong) FBSimulator *simulator;
@ -50,6 +52,21 @@
return ([self.simulator installedApplicationWithBundleID:bundleID error:error] != nil);
}
- (FBProductBundle *)applicationBundleWithBundleID:(NSString *)bundleID error:(NSError **)error
{
FBSimulatorApplication *application = [self.simulator installedApplicationWithBundleID:bundleID error:error];
if (!application) {
return nil;
}
FBProductBundle *productBundle =
[[[FBProductBundleBuilder builder]
withBundlePath:application.path]
build];
return productBundle;
}
- (BOOL)launchApplicationWithBundleID:(NSString *)bundleID arguments:(NSArray *)arguments environment:(NSDictionary *)environment error:(NSError **)error
{
FBSimulatorApplication *app = [self.simulator installedApplicationWithBundleID:bundleID error:error];

Просмотреть файл

@ -17,12 +17,11 @@
/**
Starts testing application using test bundle
@param application the Application to test.
@param configuration configuration used to launch test runner application
@param testBundlePath path to XCTest bundle used for testing
@param workingDirectory xctest working directory
@return the reciever, for chaining.
*/
- (instancetype)startTestRunnerApplication:(FBSimulatorApplication *)application configuration:(FBApplicationLaunchConfiguration *)configuration testBundlePath:(NSString *)testBundlePath workingDirectory:(NSString *)workingDirectory;
- (instancetype)startTestRunnerLaunchConfiguration:(FBApplicationLaunchConfiguration *)configuration testBundlePath:(NSString *)testBundlePath workingDirectory:(NSString *)workingDirectory;
@end

Просмотреть файл

@ -24,16 +24,18 @@
@implementation FBSimulatorInteraction (XCTest)
- (instancetype)startTestRunnerApplication:(FBSimulatorApplication *)application configuration:(FBApplicationLaunchConfiguration *)configuration testBundlePath:(NSString *)testBundlePath workingDirectory:(NSString *)workingDirectory
- (instancetype)startTestRunnerLaunchConfiguration:(FBApplicationLaunchConfiguration *)configuration testBundlePath:(NSString *)testBundlePath workingDirectory:(NSString *)workingDirectory
{
NSParameterAssert(application);
NSParameterAssert(configuration);
NSParameterAssert(testBundlePath);
NSParameterAssert(workingDirectory);
[FBFoundationInitializer initializeTestingEnvironment];
return [self interactWithBootedSimulator:^ BOOL (NSError **error, FBSimulator *simulator) {
FBSimulatorTestPreparationStrategy *testPrepareStrategy =
[FBSimulatorTestPreparationStrategy strategyWithApplicationPath:application.path
testBundlePath:testBundlePath
workingDirectory:workingDirectory
[FBSimulatorTestPreparationStrategy strategyWithTestRunnerBundleID:configuration.bundleID
testBundlePath:testBundlePath
workingDirectory:workingDirectory
];
FBSimulatorControlOperator *operator = [FBSimulatorControlOperator operatorWithSimulator:self.simulator];
FBXCTestRunStrategy *testRunStrategy = [FBXCTestRunStrategy strategyWithDeviceOperator:operator testPrepareStrategy:testPrepareStrategy logger:simulator.logger];

Просмотреть файл

@ -12,6 +12,8 @@
@property (nonatomic, strong) id<FBFileManager> fileManager;
@property (nonatomic, strong) id<FBCodesignProvider> codesignProvider;
@property (nonatomic, copy) NSString *bundlePath;
@property (nonatomic, copy) NSString *bundleID;
@property (nonatomic, copy) NSString *binaryName;
@property (nonatomic, copy) NSString *workingDirectory;
- (Class)productClass;

Просмотреть файл

@ -86,6 +86,22 @@
*/
- (instancetype)withBundlePath:(NSString *)bundlePath;
/**
@optional
@param bundleID bundle id of the application, If passed will, skip loading information from plist
@return builder
*/
- (instancetype)withBundleID:(NSString *)bundleID;
/**
@optional
@param binaryName binary name of the application, If passed will, skip loading information from plist
@return builder
*/
- (instancetype)withBinaryName:(NSString *)binaryName;
/**
@param workingDirectory if not nil product bundle will be copied to this directory
@return builder

Просмотреть файл

@ -65,6 +65,18 @@
return self;
}
- (instancetype)withBundleID:(NSString *)bundleID
{
self.bundleID = bundleID;
return self;
}
- (instancetype)withBinaryName:(NSString *)binaryName
{
self.binaryName = binaryName;
return self;
}
- (instancetype)withCodesignProvider:(id<FBCodesignProvider>)codesignProvider
{
self.codesignProvider = codesignProvider;
@ -106,8 +118,8 @@
bundleProduct.path = targetBundlePath;
bundleProduct.filename = targetBundlePath.lastPathComponent;
bundleProduct.name = targetBundlePath.lastPathComponent.stringByDeletingPathExtension;
bundleProduct.bundleID = infoPlist[@"CFBundleIdentifier"];
bundleProduct.binaryName = infoPlist[@"CFBundleExecutable"];
bundleProduct.bundleID = self.bundleID ?: infoPlist[@"CFBundleIdentifier"];
bundleProduct.binaryName = self.binaryName ?: infoPlist[@"CFBundleExecutable"];
bundleProduct.binaryPath = (bundleProduct.binaryName ? [targetBundlePath stringByAppendingPathComponent:bundleProduct.binaryName] : nil);
return bundleProduct;
}

Просмотреть файл

@ -10,6 +10,7 @@
#import <Foundation/Foundation.h>
@class DVTAbstractiOSDevice;
@class FBProductBundle;
@class FBTestRunnerConfiguration;
/**
@ -44,6 +45,15 @@
*/
- (BOOL)isApplicationInstalledWithBundleID:(NSString *)bundleID error:(NSError **)error;
/**
Queries application with given bundleID
@param bundleID bundle ID of queried application
@param error If there is an error, upon return contains an NSError object that describes the problem.
@return applicationBundle if application is installed, otherwise nil
*/
- (FBProductBundle *)applicationBundleWithBundleID:(NSString *)bundleID error:(NSError **)error;
/**
Launches application with given bundleID, arguments & environment variables

Просмотреть файл

@ -22,27 +22,27 @@
/**
Creates and returns a strategy with given paramenters
@param applicationPath path to tested application (.app)
@param testRunnerBundleID a bundle ID of apllication used to start tests
@param testBundlePath path to test bundle (.xctest)
@param workingDirectory directory used to prepare all bundles
@returns Prepared FBSimulatorTestRunStrategy
*/
+ (instancetype)strategyWithApplicationPath:(NSString *)applicationPath
testBundlePath:(NSString *)testBundlePath
workingDirectory:(NSString *)workingDirectory;
+ (instancetype)strategyWithTestRunnerBundleID:(NSString *)testRunnerBundleID
testBundlePath:(NSString *)testBundlePath
workingDirectory:(NSString *)workingDirectory;
/**
Creates and returns a strategy with given paramenters
@param applicationPath path to tested application (.app)
@param testRunnerBundleID a bundle ID of apllication used to start tests
@param testBundlePath path to test bundle (.xctest)
@param workingDirectory directory used to prepare all bundles
@param fileManager file manager used to prepare all bundles
@returns Prepared FBSimulatorTestRunStrategy
*/
+ (instancetype)strategyWithApplicationPath:(NSString *)applicationPath
testBundlePath:(NSString *)testBundlePath
workingDirectory:(NSString *)workingDirectory
fileManager:(id<FBFileManager>)fileManager;
+ (instancetype)strategyWithTestRunnerBundleID:(NSString *)testRunnerBundleID
testBundlePath:(NSString *)testBundlePath
workingDirectory:(NSString *)workingDirectory
fileManager:(id<FBFileManager>)fileManager;
@end

Просмотреть файл

@ -21,32 +21,32 @@
@interface FBSimulatorTestPreparationStrategy ()
@property (nonatomic, copy) NSString *workingDirectory;
@property (nonatomic, copy) NSString *applicationPath;
@property (nonatomic, copy) NSString *testRunnerBundleID;
@property (nonatomic, copy) NSString *testBundlePath;
@property (nonatomic, strong) id<FBFileManager> fileManager;
@end
@implementation FBSimulatorTestPreparationStrategy
+ (instancetype)strategyWithApplicationPath:(NSString *)applicationPath
testBundlePath:(NSString *)testBundlePath
workingDirectory:(NSString *)workingDirectory
+ (instancetype)strategyWithTestRunnerBundleID:(NSString *)testRunnerBundleID
testBundlePath:(NSString *)testBundlePath
workingDirectory:(NSString *)workingDirectory
{
return
[self strategyWithApplicationPath:applicationPath
testBundlePath:testBundlePath
workingDirectory:workingDirectory
fileManager:[NSFileManager defaultManager]
[self strategyWithTestRunnerBundleID:testRunnerBundleID
testBundlePath:testBundlePath
workingDirectory:workingDirectory
fileManager:[NSFileManager defaultManager]
];
}
+ (instancetype)strategyWithApplicationPath:(NSString *)applicationPath
testBundlePath:(NSString *)testBundlePath
workingDirectory:(NSString *)workingDirectory
fileManager:(id<FBFileManager>)fileManager
+ (instancetype)strategyWithTestRunnerBundleID:(NSString *)testRunnerBundleID
testBundlePath:(NSString *)testBundlePath
workingDirectory:(NSString *)workingDirectory
fileManager:(id<FBFileManager>)fileManager
{
FBSimulatorTestPreparationStrategy *strategy = [self.class new];
strategy.applicationPath = applicationPath;
strategy.testRunnerBundleID = testRunnerBundleID;
strategy.testBundlePath = testBundlePath;
strategy.workingDirectory = workingDirectory;
strategy.fileManager = fileManager;
@ -59,19 +59,9 @@
{
NSAssert(deviceOperator, @"deviceOperator is needed to load bundles");
NSAssert(self.workingDirectory, @"Working directory is needed to prepare bundles");
NSAssert(self.applicationPath, @"Path to application is needed to load bundles");
NSAssert(self.testRunnerBundleID, @"Test runner bundle ID is needed to load bundles");
NSAssert(self.testBundlePath, @"Path to test bundle is needed to load bundles");
FBProductBundle *application =
[[[FBProductBundleBuilder builderWithFileManager:self.fileManager]
withBundlePath:self.applicationPath]
build];
// Install tested application
if (![deviceOperator installApplicationWithPath:self.applicationPath error:error]) {
return nil;
}
// Prepare XCTest bundle
NSUUID *sessionIdentifier = [NSUUID UUID];
FBTestBundle *testBundle =
@ -81,6 +71,9 @@
withSessionIdentifier:sessionIdentifier]
build];
// Prepare test runner
FBProductBundle *application = [deviceOperator applicationBundleWithBundleID:self.testRunnerBundleID error:error];
NSString *IDEBundleInjectionFrameworkPath =
[FBControlCoreGlobalConfiguration.developerDirectory stringByAppendingPathComponent:@"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/IDEBundleInjection.framework"];
FBProductBundle *IDEBundleInjectionFramework =

Просмотреть файл

@ -62,7 +62,6 @@
return nil;
}
// Get XCTStubApps process Id
pid_t testRunnerProcessID = [self.deviceOperator processIDWithBundleID:configuration.testRunner.bundleID error:error];
if (testRunnerProcessID <= 0) {
if (error) {

Просмотреть файл

@ -13,6 +13,7 @@
#import "FBDeviceOperator.h"
#import "FBFileManager.h"
#import "FBProductBundle.h"
#import "FBSimulatorTestPreparationStrategy.h"
#import "FBTestRunnerConfiguration.h"
@ -29,30 +30,30 @@
- (void)testStrategyWithMissingWorkingDirectory
{
FBSimulatorTestPreparationStrategy *strategy =
[FBSimulatorTestPreparationStrategy strategyWithApplicationPath:@""
testBundlePath:@""
workingDirectory:nil
fileManager:nil];
[FBSimulatorTestPreparationStrategy strategyWithTestRunnerBundleID:@""
testBundlePath:@""
workingDirectory:nil
fileManager:nil];
XCTAssertThrows([strategy prepareTestWithDeviceOperator:[OCMockObject niceMockForProtocol:@protocol(FBDeviceOperator)] error:nil]);
}
- (void)testStrategyWithMissingTestBundlePath
{
FBSimulatorTestPreparationStrategy *strategy =
[FBSimulatorTestPreparationStrategy strategyWithApplicationPath:@""
testBundlePath:nil
workingDirectory:@""
fileManager:nil];
[FBSimulatorTestPreparationStrategy strategyWithTestRunnerBundleID:@""
testBundlePath:nil
workingDirectory:@""
fileManager:nil];
XCTAssertThrows([strategy prepareTestWithDeviceOperator:[OCMockObject niceMockForProtocol:@protocol(FBDeviceOperator)] error:nil]);
}
- (void)testStrategyWithMissingApplicationPath
{
FBSimulatorTestPreparationStrategy *strategy =
[FBSimulatorTestPreparationStrategy strategyWithApplicationPath:nil
testBundlePath:@""
workingDirectory:@""
fileManager:nil];
[FBSimulatorTestPreparationStrategy strategyWithTestRunnerBundleID:nil
testBundlePath:@""
workingDirectory:@""
fileManager:nil];
XCTAssertThrows([strategy prepareTestWithDeviceOperator:[OCMockObject niceMockForProtocol:@protocol(FBDeviceOperator)] error:nil]);
}
@ -70,14 +71,19 @@
[[[fileManagerMock expect] andReturnValue:@YES] copyItemAtPath:@"/testBundle" toPath:@"/heaven/testBundle" error:[OCMArg anyObjectRef]];
[[[[fileManagerMock expect] andReturnValue:@YES] ignoringNonObjectArgs] writeData:[OCMArg any] toFile:xctConfigArg options:0 error:[OCMArg anyObjectRef]];
FBProductBundle *productBundle =
[[[FBProductBundleBuilder builderWithFileManager:fileManagerMock]
withBundlePath:@"/app"]
build];
OCMockObject<FBDeviceOperator> *deviceOperatorMock = [OCMockObject mockForProtocol:@protocol(FBDeviceOperator)];
[[[deviceOperatorMock expect] andReturnValue:@YES] installApplicationWithPath:@"/app" error:[OCMArg anyObjectRef]];
[[[deviceOperatorMock expect] andReturn:productBundle] applicationBundleWithBundleID:@"bundleId" error:[OCMArg anyObjectRef]];
FBSimulatorTestPreparationStrategy *strategy =
[FBSimulatorTestPreparationStrategy strategyWithApplicationPath:@"/app"
testBundlePath:@"/testBundle"
workingDirectory:@"/heaven"
fileManager:fileManagerMock];
[FBSimulatorTestPreparationStrategy strategyWithTestRunnerBundleID:@"bundleId"
testBundlePath:@"/testBundle"
workingDirectory:@"/heaven"
fileManager:fileManagerMock];
FBTestRunnerConfiguration *configuration = [strategy prepareTestWithDeviceOperator:deviceOperatorMock error:nil];
NSDictionary *env = configuration.launchEnvironment;