EarlGrey icon indicating copy to clipboard operation
EarlGrey copied to clipboard

How to restart app before every test case and test suite in EarlGrey?

Open selin194 opened this issue 6 years ago • 17 comments

Hi all, I have a question. I want to restart app like in XCUITests before each test case in EarlGrey. As far as I searched I found that I need to call a function via AppDelegate. And I copy the contents of applicationWillTerminate(_ application: UIApplication) to the newly written restartAppForTesting(with appDelegate: AppDelegate) function. And call this function in tearDown() method of my test suite like below:

import EarlGrey

 override func setUp() {
        super.setUp()
 }

  override func tearDown() {
       super.tearDown()
       let appDelegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate

       //This function is same with the applicationWillTerminate(_ application: UIApplication)
       appDelegate.restartAppForTesting(with: appDelegate)

       // wait for app restarts
        sleep(20)
   }

   func testTesCase1() {
      //Test logic
   }

   func testTestCase2() {
    //Test logic 
   }

However I get an error before testTestCase2() is being executed. The error is: test runner exited with code 1 before finishing running test

What can I do? Is there a proper way for me to restart app before each test case and test suite? Thanks in advance!

selin194 avatar Sep 15 '19 11:09 selin194

Earlgrey 1 doesn’t support this feature. You should use Earlgrey 2 which is built on top of XCUITest and allows launching and terminating app by calling xcuiapplication methods directly.

khandpur avatar Sep 15 '19 19:09 khandpur

Thank you for replying @khandpur. From the link here https://github.com/google/EarlGrey/blob/2.0.0/docs/setup.md EarlGrey 2.0 does not have Cocoapods support. Is that means everyone in the project should set up EarlGrey manually, right?

selin194 avatar Sep 15 '19 20:09 selin194

@tirodkar fyi

khandpur avatar Sep 15 '19 21:09 khandpur

@selin194 EarlGrey 2.0 has support for black-box testing with instructions over here.

https://github.com/google/EarlGrey/blob/earlgrey2/docs/cocoapods-setup.md

I'll add a link to it in the setup doc. Thanks! Tell me if you run into issues.

tirodkar avatar Sep 15 '19 21:09 tirodkar

Hey @tirodkar ! I install EarlGreyApp and EarlGreyTest pods to our project. However EarlGrey.swift file is not installed as in EarlGrey pod. Do I miss something? Additionally, do I need to import EarlGreyTest , right? (By the way I already execute gem install earlgrey)

Edit: I added EarlGrey.swift file manually, after that I tried to write a simple test case like below:

   import XCTest
   import EarlGreyTest

   class AccessibilityTests: XCTestCase {
      private var closeIconMatcher = grey_accessibilityID("closeIcon")

       override func setUp() {
           super.setUp()
           continueAfterFailure = false
           XCUIApplication().launch()
    }

       override func tearDown() {
            super.tearDown()
     }

        func testExample() {
                  EarlGrey.selectElement(with: closeIconMatcher)
            .perform(grey_tap())
       }
}

and I get an error that says: Host background port not assigned. Application under test may have failed to launch and/or does not link to EarlGrey's AppFramework.

Here is my Podfile:

   target 'myApp' do
       // My other pods
       pod 'EarlGreyApp'
   end

   target 'AccessibilityEarlGrey2' do
        inherit! :search_paths # Required for not double-linking libraries in the app and test targets.
        pod 'EarlGreyTest'
  end

Do I need to add something? Thank you!

selin194 avatar Sep 16 '19 08:09 selin194

@selin194 Did you get the solution? I am also getting the same console log.

"Host background port not assigned. Application under test may have failed to launch and/or does not link to EarlGrey's AppFramework."

@tirodkar do you have any insight?

anshulpara avatar Nov 04 '19 14:11 anshulpara

@anshulpara I do not find a solution, do you have any idea about this?

selin194 avatar Nov 04 '19 18:11 selin194

I haven't added gem support for EarlGrey 2.0 yet. Can you drag / drop EarlGrey.swift into your folder?

https://github.com/google/EarlGrey/blob/earlgrey2/TestLib/Swift/EarlGrey.swift

tirodkar avatar Nov 04 '19 19:11 tirodkar

I will try this, I guess I was adding the wrong version of this file.

selin194 avatar Nov 05 '19 06:11 selin194

Hi @selin194, did it work for you? I have the same issue.

maroleks avatar Dec 02 '19 09:12 maroleks

I have the same issue too, have you fix it @maroleks @selin194 ?

CblPOB avatar Dec 09 '19 09:12 CblPOB

Hey @maroleks and @CblPOB. I have not tried this yet. Are you trying https://github.com/google/EarlGrey/blob/earlgrey2/TestLib/Swift/EarlGrey.swift this file, right?

selin194 avatar Dec 09 '19 10:12 selin194

@selin194 yes, i have it in my folder already and it seems that it haven't affect this issue

CblPOB avatar Dec 09 '19 10:12 CblPOB

@CblPOB, @selin194 same here... same file and same (or no-) result

maroleks avatar Dec 09 '19 12:12 maroleks

@selin194 , @CblPOB and @maroleks : I was also getting same error:

"Host background port not assigned. Application under test may have failed to launch and/or does not link to EarlGrey's AppFramework."

When I looked into Xcode console logs, there was an error (which actually was ignored and the app was launched) related to AppFramework signing in start. I had this issue because my App and the UI Testing bundles were signed by different team ids due to which iOS was not loading the AppFramework. Once I enabled signing using same team id, I was able to run the tests comfortably with EarlGrey.

Note: I faced this issue on real device.

dispatchMain avatar Jan 08 '20 17:01 dispatchMain

Thanks for sharing your knowledge @Ad1991! Can you now restart the app using EarlGrey 2.0 by updating team IDs?

selin194 avatar Jan 09 '20 07:01 selin194

@selin194: Well, I was getting this issue at first launch itself:

"Host background port not assigned. Application under test may have failed to launch and/or does not link to EarlGrey's AppFramework."

Which I fixed using the mechanism I in comment mentioned above. However, since you mentioned of restart, when I tried to restart using terminate() and launch() methods of XCUIApplication, I noticed that I am now getting the same error at second launch. When I looked into logs of the application (not runner application) I found out that system was not able to inject the AppFramework library at second launch:

"dyld: warning: could not load inserted library '@executable_path/Frameworks/AppFramework.framework/AppFramework,@executable_path/Frameworks/AppFramework.framework/AppFramework' into hardened process because image not found"

I was a bit confused at start as to why system would load same library at first launch but not in subsequent launches. Then I noticed the library path it was loading and I would see that AppFramework path was duplicated. I looked up and found this code (XCUIApplication+GREYEnvironment.m:26):

- (void)grey_configureApplicationForLaunch {
  NSMutableDictionary *mutableEnv = [self.launchEnvironment mutableCopy];
  NSString *insertionKey = @"DYLD_INSERT_LIBRARIES";
  NSString *insertionValue = @"@executable_path/Frameworks/AppFramework.framework/AppFramework";
  NSString *alreadyExistingValue = [mutableEnv valueForKey:insertionKey];
  if (alreadyExistingValue) {
    //Below is the line causing library path to be duplicated.
    insertionValue = [NSString stringWithFormat:@"%@,%@", alreadyExistingValue, insertionValue];
  }
  [mutableEnv setObject:insertionValue forKey:insertionKey];
  self.launchEnvironment = [mutableEnv copy];
}

See the comment inside if case. If you change that code to as below, it should launch second time properly as well:

if (alreadyExistingValue && ![alreadyExistingValue containsString:insertionValue]) {
    insertionValue = [NSString stringWithFormat:@"%@,%@", alreadyExistingValue, insertionValue];
}

@tirodkar : I hope the above is useful for you as well.

dispatchMain avatar Jan 09 '20 16:01 dispatchMain