velapanur
velapanur

Reputation: 335

XCUITest Class teardown isnt deleting the app. But works if its instance teardown. What am I doing wrong?

I have a class teardown which is trying to remove the app, but it doesn't recognize app.terminate().

class DeviceSettingsUtilities : UITestUtilities {
func removeApp(productName:String){
        print("in teardown")
        let springboard = XCUIApplication(bundleIdentifier: "com.apple.springboard")
        XCUIApplication().terminate() // this does nothing
        XCUIApplication(bundleIdentifier: "com.xxx.xxxx").terminate()//this does nothing too, but this works when called as an instance teardown
        sleep(5)
        springboard.activate()
        let icon = springboard.icons.matching(identifier: productName).firstMatch
// icon.exists is false when called as a class teardown
// icon.exists is true when called as an instance teardown
        if icon.exists {
            let iconFrame = icon.frame
            let springboardFrame = springboard.frame
            icon.press(forDuration:1.3)
            springboard.coordinate(withNormalizedOffset: CGVector(dx: ((iconFrame.minX + 3) / springboardFrame.maxX), dy:((iconFrame.minY + 3) / springboardFrame.maxY))).tap()
            sleep(5)
            springboard.buttons["Delete"].firstMatch.tap()
            sleep(5)
        }
        XCUIApplication().terminate()
    }

}

This is being called in the test case class teardown method as shown below

override class func tearDown() {
    super.tearDown()
    let deviceSettings = DeviceSettingsUtilities()
    deviceSettings.removeApp(productName: ProductName.rawValue)
}

This just doesnt delete the app, But if i change class func tearDown() to func tearDown() , it deletes the app with no problem. Not sure what i am missing. Any suggestions ?

Upvotes: 0

Views: 4440

Answers (3)

Václav
Václav

Reputation: 1000

This seems like a bug in latest Xcode 10. XCUIApplication.terminate() doesn't seem to work in tearDown() when declared as class.

This can be solved in two ways:

The first option is to use:

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

instead of:

override class func tearDown() {…} 

Or, terminate the app differently (press home button, open different app...). However, I would use the first way.

Also consider reporting this to Apple, so they can fix it.

Edit: This has nothing to do with app state (XCUIApplication().state.rawValue), since it is same in test and in tearDown() (4 = running foreground). Also - official documentation says that .terminate() will terminate app, which has a debug session with Xcode, but the debug session is active in tearDown() as well. So it is really probably a bug in Xcode.

Upvotes: 2

Prakash Saravanan
Prakash Saravanan

Reputation: 656

I'm using the below workaround to terminate the app after last test case of a class.

class BaseClass: XCTestCase {

        static var LastTestCaseName: String = ""

        override class func setUp() {
            LastTestCaseName = defaultTestSuite.tests.last!.name
            super.setUp()
        }

        override func tearDown() {
            let app = XCUIApplication()
            if BaseClass.LastTestCaseName == testRun?.test.name {
                app.terminate()
            }
        }
    }

Upvotes: 1

Oletha
Oletha

Reputation: 7649

The app is not being reset when you put the code in the class tearDown method because that method only runs once all the tests in the class are complete. The instance tearDown is the best place to put code that you want to run after every test.

From Apple's documentation:

For each class, testing starts by running the class setup method. For each test method, a new instance of the class is allocated and its instance setup method executed. After that it runs the test method, and after that the instance teardown method. This sequence repeats for all the test methods in the class. After the last test method teardown in the class has been run, Xcode executes the class teardown method and moves on to the next class. This sequence repeats until all the test methods in all test classes have been run.

Upvotes: 1

Related Questions