0

I am trying to implement UI testing with BDD using Cucumberish framework. I understand quite well the Feature files parsing system and I managed to tests some UI elements of the main screen.

However I would like to load any controller from storyboard before using UI testing on the corresponding screen.

Here is my initialization code:

@objc class CucumberishSwiftInit: NSObject {
@objc class func CucumberishSwiftInit()
{
    var application : XCUIApplication!
    //A closure that will be executed just before executing any of your features
    beforeStart { () -> Void in
        application = XCUIApplication()
    }
    //A Given step definition
    Given("the app is running") { (args, userInfo) -> Void in
        application.launch()
        let bundle = Bundle.main

        // I double checked the storyboard name and I can access it in my Unit Tests target
        // application crashes here
        let storyboard = UIStoryboard(name: "Main", bundle: bundle)

        // never executed 
        Swift.print("storyboard \(storyboard)")
    }
    let bundle = Bundle(for: CucumberishSwiftInit.self)

    Cucumberish.executeFeatures(inDirectory: "Features", from: bundle, includeTags: nil, excludeTags: ["skip"])
}
}

Some feature file:

@run @welcome
Feature: Some feature
Some feature desc

Scenario: Can load screen
    Given the app is running
    ...

The application crashed on the UIStoryboard init statement, caught "NSInvalidArgumentException", "Could not find a storyboard named 'Main' in bundle NSBundle (loaded). I have no clue why as it is working using with my unit tests.

Super Jade
  • 5,609
  • 7
  • 39
  • 61
michael-martinez
  • 767
  • 6
  • 24

1 Answers1

1

The error you're getting is due to the fact that the .storyboard file you are trying to load is not part of the bundle of the application you are running.

The reason that's happening is that when you run a UI test your code is not running in the same process as your application, and it can only interact with it through the XCUIApplication proxy. (The mechanics might be slightly different, but that's gist, unfortunately there's little documentation that I can link.)

UI testing is a different style of testing than what you can do with XCTest. Programmatically loading an instance of a screen from a .storyboard is not possible.

In other words, you can't use any code from your app in your UI tests, but rather have to interact with it like a real user would, and write assertions for what's on the screen.

mokagio
  • 16,391
  • 3
  • 51
  • 58
  • Thanks for your help ! thus if I don't have access to the .storyboard files, I must manually go to specific screens. Also an interesting alternative here using launch arguments: https://stackoverflow.com/questions/49020329/is-it-possible-to-open-a-screen-directly-in-xcuitest. If the UI tests are intended to test the screens inner working, this is an interesting approach as it is agnostic to how the application segues evolves. – michael-martinez Feb 17 '19 at 16:01
  • Happy to be useful @michael-martinez :) The approach in the linked question is ingenious but comes with a lot of overhead in the production code to support the ability to run the UI test. I would encourage anyone considering implementing it to value up the cost of that extra code in their production codebase. Code is a liability, the less we can write the better. – mokagio Feb 18 '19 at 05:44