Closed RainerSchwarze closed 8 years ago
I'm also trying to use this. I'm expecting to use the launch arguments in my app, are these only available on the UI test classes? Because the text gives all indication that it should be use on the standard app code.
@RainerSchwarze Do you have any updates on this? Did you move on or used other strategy?
@Orgmir I added a helper method to my screenshot test case:
- (NSString*) argValueForKey:(NSString*)key inApp:(XCUIApplication*)app {
NSInteger index = [app.launchArguments indexOfObject:key];
if (index==NSNotFound || index>=app.launchArguments.count-1) {
return nil;
}
return [app.launchArguments objectAtIndex:index+1];
}
and I use it like this in the setUp
method: (_run...
are BOOL instance variables which are tested in the individual test methods)
NSString *testsel = [self argValueForKey:@"-app_uitests" inApp:app];
if ([testsel isEqualToString:@"appstorescreenshots"]) {
_runAppStoreScreenshots = YES;
} else if ([testsel isEqualToString:@"websitescreenshots"]) {
_runWebsiteScreenshots = YES;
}
The launch_arguments
option is for setting launch arguments on the app (app.launchArguments
), and creating a screenshot matrix if multiple argument sets are specified.
You must call setupSnapshot
before you launch the main app like so
override func setUp() {
super.setUp()
let app = XCUIApplication()
setupSnapshot(app)
app.launch()
}
I see how the documentation can be confusing, we should make it clearer.
I do like the idea of making the arguments available to the UI Tests, will need @KrauseFx's input on this.
@RainerSchwarze from the snippet you posted, could I recommend creating separate Schemes or Targets for your different sets of UI Tests. You can edit a scheme and select a subset of tests for it to run, or create a new UI Testing target and keep the tests separate.
Use this Snapfile in the Snapshot Example project.
@Ashton-W Thanks for your information. I already call setupSnapshot in setUp in the right sequence. My UITests are separated from the screenshots using schemes and targets; so there will be no problem extending that to the different kinds of screenshot "runs".
I'm having a similar issue, trying to use the recommended approach up above. I can't even figure out how to log output for debugging purposes in the UITest. NSLog and print don't make it to the terminal. Any documentation on how to actually debug using logging?
@owurman I believe that I found the log output in a file. When you run fastlane / snapshot there will be a console output indicating the current setup like --- iPhone 5 - en-US ---
. Below that is a long line starting with $ set -o pipefail ...
. At the end of that line you will see | tee '/Some/File/name' | xcpretty
. This shows your log file (it is huge - and i hope I remember correctly...).
@RainerSchwarze Thanks for the tip. It doesn't look like this log file is picking up "print" or "NSLog" output, however. At least, not from the UI Test...
Maybe you can help me compare what I'm doing to what you're doing? Although I'm using Swift...
Environment configuration: ENV["SNAPSHOT_PROTOCOL_INDEX"] ||= "0,1"
Snapfile: launch_arguments(["-snapshot_protocol_index #{ENV["SNAPSHOT_PROTOCOL_INDEX"]}"])
The test:
func argValueForKey(key:String, app:XCUIApplication) -> String? {
print("App launchArguments: %@", app.launchArguments.description)
NSLog("App launchArguments: %@", app.launchArguments.description)
if let index = app.launchArguments.indexOf(key) {
return app.launchArguments[index+1]
} else {
return nil
}
}
Then later...
let snapshot_index = argValueForKey("-snapshot_protocol_index", app:app)
It seems to always be returning nil, however...
I'm frankly not even seeing where the launch arguments are being passed in by fastlane... ETA: Never mind, I see that's it's hacked via a file in /tmp that's read in by setLaunchArguments() in SnapshotHelper.swift
@owurman Are you trying to use launch arguments in your testing target? They should be used in the app. Something like https://gist.github.com/vpolouchkine/4fa22270fde1c882c56f
@vpolouchkine Yes, I need them in my testing target, too... is that not possible? Seems like it should be available in app.launchArguments.
OK, I see that the problem is that app.launchArguments is an empty array. I incorrect assumed that XCUIApplication() returned a singleton.
I managed to get it to work by calling setupSnapshot(app) again within the test itself. It's hacky, but so is "setupSnapshot" to begin with ;)
:+1:
Just some additional background for anyone who stumbles on this issue in the future:
launch_arguments are sent to the test from snapshot via a hack that puts them in /tmp/snapshot-launch_arguments.txt
This text file is read in by setLaunchArguments(app) in SnapshotHelper.swift, which is in turn called by setupSnapshot(app) in SnapshotHelper.swift.
When running the actual test you don't have access to the XCUIApplication (app) that was used to setup the launch arguments... or at least I don't know how to get to it. Therefore you have to call setupSnapshot(app) again in order to set up the launch arguments (or do your own direct read-in of the file). Here's how my code ended up:
func argValueForKey(key:String, app:XCUIApplication) -> String? {
if let index = app.launchArguments.indexOf(key) {
return app.launchArguments[index+1]
} else {
return nil
}
}
func testExample() {
let app = XCUIApplication()
/*
* This will read in the launch arguments again so we can use
* them in the UI test.
*/
setupSnapshot(app)
// ...
let snapshot_index = argValueForKey("-snapshot_protocol_index", app:app)
if let snapshot_index_unwrapped = snapshot_index {
// ...
@owurman Hmmm. I'm calling setupSnapshot
in the setUp
method of the test class - no need to call it in the test method itself.
@RainerSchwarze But then how do you access the launchArguments from within the test? I'd need the same XCUIApplication object. I guess I could save that to a global variable...
@owurman Yes, I used properties and in the test methods I check the properties' values:
@interface MyAppUISnapshotTests : XCTestCase
@property (assign, nonatomic) BOOL runAppStoreScreenshots;
@property (assign, nonatomic) BOOL runWebsiteScreenshots;
@end
@implementation MyAppUISnapshotTests
- (void)setUp {
[super setUp];
XCUIApplication *app = [[XCUIApplication alloc] init];
[SnapshotHelper setupSnapshot:app];
NSString *testsel = [self argValueForKey:@"-myapp_uitests" inApp:app];
NSLog(@"testsel = %@ / args = %@", testsel, app.launchArguments);
if ([testsel isEqualToString:@"appstorescreenshots"]) {
_runAppStoreScreenshots = YES;
} else if ([testsel isEqualToString:@"websitescreenshots"]) {
_runWebsiteScreenshots = YES;
}
[app launch];
}
- (void)testAppStoreScreenshots {
if (!_runAppStoreScreenshots) {
NSLog(@"AppStore Screenshots are skipped.");
return;
}
...
Your way would seem to make a lot more sense ;)
This issue was migrated to https://github.com/fastlane/fastlane/issues/2514. Please post all further comments there.
fastlane
is now a mono repo, you can read more about the change in our blog post. All tools are now available in the fastlane main repo :rocket:
The snapshot README.md includes this:
Part of my
fastfile
:In my UITest the setUp method looks like this:
(The logging output is repeated in the test methods.)
However, the launch argument only exists in
XCUIApplication.launchArguments
. The same applies to-FASTLANE_SNAPSHOT
- it only exists in thelaunchArguments
array.Did I do something wrong when accessing
NSUserDefaults
orNSProcessInfo
? Is this a documentation bug or a software bug?(I'm working in an Objective-C project and wrapped most of SnapshotHelper.swift with
@objc class SnapshotHelper : NSObject {
...}
in case this makes any difference.) I'm using snapshot 1.4.3.Thanks