Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

add device agnostic tests & add helpful assertion for device agnostic tests #137

Merged
merged 1 commit into from
Jan 8, 2016

Conversation

bgerstle
Copy link
Contributor

@bgerstle bgerstle commented Dec 9, 2015

Our app doesn't have a window when run as a test host, which results in keyWindow being nil. This could also happen if your test target is a "Logic Test", and not an "Application Test."

$ ls -1 WikipediaUnitTests/ReferenceImages_64/NSAttributedString_WMFModifyTests
[email protected]
testChangeGreenBackgroundColorsToBlue_iPhone_Simulator8_4_0x0@2x.png
[email protected]
[email protected]
[email protected]

I've added an assertion so others can get clearer feedback about what's going wrong and how to fix it. FBSnapshotTestCase could arguably create a keyWindow implicitly, but I figured it's better to let users set up their test host properly instead of implicitly relying on the library to do it for them.

@facebook-github-bot
Copy link

Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla - and if you have received this in error or have any questions, please drop us a line at [email protected]. Thanks!

@facebook-github-bot
Copy link

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks!

bgerstle added a commit to wikimedia/wikipedia-ios that referenced this pull request Dec 9, 2015
- re-record all snapshots
- point to FBSnapshotTestCase fork w/ a fix for screen size suffix (PR
  is already up:
  facebookarchive/ios-snapshot-test-case#137)
- add "WMFVisualTestBatchRecordMode" to make it easier to re-record all
  snapshot tests
@bgerstle
Copy link
Contributor Author

bgerstle commented Dec 9, 2015

looks like I need to download iOS 9.0 sim and re-record snapshots. downloading now... ⏳

@@ -34,7 +34,7 @@ BOOL FBSnapshotTestCaseIs64Bit(void)
NSString *FBDeviceAgnosticNormalizedFileName(NSString *fileName)
{
UIDevice *device = [UIDevice currentDevice];
CGSize screenSize = [[UIApplication sharedApplication] keyWindow].bounds.size;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this change is OK.
UIWindow != UIScreen -> UIWindow is unique for application (especially useful for split view), and UIScreen is for whole device.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true, but I figured using the screen would:

  • Be equivalent to the window in most cases
  • Work when the library is integrated as a framework (where keyWindow does not)

Maybe a more comprehensive way to solve this would be to generate the suffix based on the view being tested, which is probably what you really want anyway. This makes even more sense when you consider that snapshots are generated based on the bounds of the specified view, even creating and "keying" a window if necessary.[0]

0: https://github.com/facebook/ios-snapshot-test-case/blob/master/FBSnapshotTestCase/Categories/UIImage+Snapshot.m#L46

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, we could check if the keyWindow is nil and if it is, create a window with the [[UIScreen mainScreen] bounds]

How does this sound?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, just had a realization: the problem doesn't have anything to do with frameworks. Our app short-circuits itself when being run as the test host, which means no AppDelegate, which means no keyWindow.

So, this is more about handling our specific edge case, which means that a window should be made the keyWindow before suffixes are generated. At which point, I'm wondering if we should be using a "dummy" app delegate (which just has a dummy window), or FBSnapshotTestCase should install one for me (e.g. if you were running a Logic Tests target which didn't even have a host).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had similar problem:
I write some framework which is using UIApplication. Same framework doesn't have UIApplication, so I created TestApp, which hosts tests.
So check if this resolve your problem:

  1. Add new Application target
  2. Choose your framework test target
  3. Go to general tab
  4. Set your new Application target as Host Application
  5. Make sure that your Application target contains framework tests in test schema

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice, if that works maybe we can assert and explain how to solve this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Grubas7 the short-circuit is intentional, and our app is already the "Host" for our tests. This removes the unnecessary "link in both targets" step when adding new app code.

My question to you guys is, should FBSnapshotTestCase be defensive by setting the keyWindow itself (which it already tries to do), and if so, should it guarantee that keyWindow is available at file suffix generation time? For example, we could use a category on UIApplication that gets or creates a key window.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My question above determines whether the solution should be either:

  • Add an assertion and explain what users should do (set a host app or otherwise create a key window when visual tests are running)
  • Create a keyWindow manually if necessary

@bgerstle
Copy link
Contributor Author

@Grubas7 @nscoding I reverted my change using UIScreen and added an assertion instead. This should prompt users (like me) who don't have a key window to go ahead and create one.

@bgerstle bgerstle changed the title add device agnostic tests & use screen for filename size suffix add device agnostic tests & add helpful assertion for device agnostic tests Dec 12, 2015
@Grubas7
Copy link
Contributor

Grubas7 commented Dec 13, 2015

@bgerstle Cool. I wonder if there should be some info about this in README. @nscoding ?

{
UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
redView.backgroundColor = [UIColor redColor];
FBSnapshotVerifyView(redView, nil);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Travis is hitting the assertion that you added, why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, will have to investigate..
On Sun, Dec 13, 2015 at 17:30 Patrick Chamelo [email protected]
wrote:

In
FBSnapshotTestCaseDemo/FBSnapshotTestCaseDemoTests/FBSnapshotTestCaseDeviceAgnosticTests.m
#137 (comment)
:

+@EnD
+
+@implementation FBSnapshotTestCaseDeviceAgnosticTests
+
+- (void)setUp
+{

  • [super setUp];
  • self.deviceAgnostic = YES;
  • self.recordMode = NO;
    +}

+- (void)testViewSnapshot
+{

  • UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
  • redView.backgroundColor = [UIColor redColor];
  • FBSnapshotVerifyView(redView, nil);

Travis is hitting the assertion that you added, why?


Reply to this email directly or view it on GitHub
https://github.com/facebook/ios-snapshot-test-case/pull/137/files#r47451523
.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the keyWindow is nil... 😖 Even though the app delegate is certainly making it key and visible. Any ideas?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also @Grubas7 this is why the tests were added

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I:

  • Somehow wait for the application to have a key window, maybe using expectationWithPredicate?
  • Fall back to the application's delegate's window?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you suggest? poll keyWIndow in FBSnapshotTestCase.setUp? e.g.:

- (void)setUp 
{
  // other stuff
  [self expectationWithPredicate:[NSPredicate predicateWithBlock:^ (...) {
    return evaluatedObject.keyWindow != nil;
  } ...];
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I had to look at it a bit to figure out what is going on and there are a couple of issues:

  1. The build script that I added on travis is building and testing both iPhone 5 and iPhone 6, so we have to record the image for both of these devices.
  2. The build script runs the FBSnapshotControllerTests and in particular testFailedImageWithDeviceAgnosticShouldHaveModelOnName. These tests don't have an application associated with, so we hit the assertion. Maybe we can make the window a parameter and simply write tests to make sure that FBDeviceAgnosticNormalizedFileName is working as expected.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bgerstle thoughts on my latest comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh I didn't see the updated commits

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nscoding yeah, sorry I didn't respond, but better late than never:

The build script that I added on travis is building and testing both iPhone 5 and iPhone 6, so we have to record the image for both of these devices.

I already figured that out when Travis failed and downloaded/recorded the proper screenshots.

testFailedImageWithDeviceAgnosticShouldHaveModelOnName. These tests don't have an application associated with, so we hit the assertion.

Those tests are in the Demo project, which does have a host application (see above screenshot). I think the problem was that UIImage+Snapshot was causing issues when installing a "dummy" window when given a view without a window. This somehow caused the keyWindow to return nil when device-agnostic tests were run—which I determined after seeing each test pass in isolation. As a result, I've modified UIImage+Snapshot to use the application's keyWindow if the given view doesn't have a window (or if it isn't a window itself). Let me know if you think this is acceptable.

Maybe we can make the window a parameter and simply write tests to make sure that FBDeviceAgnosticNormalizedFileName is working as expected.

That could be useful for verifying the formatting of test names (to prevent unintended regressions and thus break tests for users), but doesn't address the problems targeted by this PR.

bgerstle added a commit to wikimedia/wikipedia-ios that referenced this pull request Dec 28, 2015
- re-record all snapshots
- point to FBSnapshotTestCase fork w/ a fix for screen size suffix (PR
  is already up:
  facebookarchive/ios-snapshot-test-case#137)
- add "WMFVisualTestBatchRecordMode" to make it easier to re-record all
  snapshot tests
@bgerstle
Copy link
Contributor Author

@Grubas7 @nscoding this should be ready to go, see my latest comment for a brief explanation on the approach and c9a9530 for the implementation


@implementation UIApplication (StrictKeyWindow)

- (UIWindow*)fb_strictKeyWindow {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing space before asterisk.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you guys considered using uncrustify or clang-format? 😅 While I'm at it, should I remove the comment headers (Created by Brian Gerstle etc.)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

went ahead and did it anyway

@Grubas7
Copy link
Contributor

Grubas7 commented Dec 28, 2015

Looks good 👍

@bgerstle
Copy link
Contributor Author

@Grubas7 thanks for the feedback! all your comments should be addressed 👌

@Grubas7
Copy link
Contributor

Grubas7 commented Dec 29, 2015

@bgerstle could you squash your commits?

@bgerstle bgerstle force-pushed the master branch 2 times, most recently from 027784b to c2b8911 Compare December 29, 2015 16:04
@bgerstle
Copy link
Contributor Author

@Grubas7 squashed & amended commit message


@implementation UIApplication (StrictKeyWindow)

- (UIWindow *)fb_strictKeyWindow {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new line before {

@nscoding
Copy link
Contributor

nscoding commented Jan 3, 2016

Thank you for working on this, it looks great, I left a couple of comments (nit picks really).

@bgerstle
Copy link
Contributor Author

bgerstle commented Jan 3, 2016

@nscoding addressed all of your comments, including the iPhone 6 screen size issue (and re-recorded reference image), squashed, and re-pushed

@nscoding
Copy link
Contributor

nscoding commented Jan 3, 2016

testSuccessfulComparisonOfDeviceAgnosticReferenceImages tests are failing, it's looking for 320x568 (iPhone 5 right? but we didn't provide this one)

@bgerstle
Copy link
Contributor Author

bgerstle commented Jan 3, 2016

Ahh that's different now too, as it used to be 320x480, forgot to re-record
those
On Sun, Jan 3, 2016 at 18:20 Patrick Chamelo [email protected]
wrote:

testSuccessfulComparisonOfDeviceAgnosticReferenceImages tests are failing,
it's looking for 320x568 (iPhone 5 right? but we didn't provide this one)


Reply to this email directly or view it on GitHub
#137 (comment)
.

Use UIApplication.keyWindow instead of a manually-created & installed
window when snapshotting a view w/o a window.  This prevents keyWindow
from being `nil` when generating device-agnostic reference image
filenames.

Accessing keyWindow is done through a category, so as to always throw an
assertion if it is nil, instructing developers to make sure their tests
have a host application w/ a key window.
@bgerstle
Copy link
Contributor Author

bgerstle commented Jan 4, 2016

@nscoding should be good now 🏁

@@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the launch screen fixes the issue where the app doesn't fill the
screen.

On Fri, Jan 8, 2016 at 12:50 Patrick Chamelo [email protected]
wrote:

In FBSnapshotTestCaseDemo/FBSnapshotTestCaseDemo/Launch Screen.storyboard
#137 (comment)
:

@@ -0,0 +1,50 @@
+
+

Do we need this?


Reply to this email directly or view it on GitHub
https://github.com/facebook/ios-snapshot-test-case/pull/137/files#r49236579
.

nscoding added a commit that referenced this pull request Jan 8, 2016
add device agnostic tests & add helpful assertion for device agnostic tests
@nscoding nscoding merged commit e42af8b into facebookarchive:master Jan 8, 2016
ksuther added a commit to ksuther/ios-snapshot-test-case that referenced this pull request Mar 24, 2016
This happens when snapshotting the key window.
This was introduced by facebookarchive#137.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants