This line should be added to the app delegate didLaunchWithOptions
method
class AppDelegate
def application(application, didFinishLaunchingWithOptions:launchOptions)
return true if RUBYMOTION_ENV == 'test'
# ...
This pretty much returns if the app is in testing mode. This is important because when running tests a window should not be created. Specs automatically create a window and controller (shown below) so having the app delegate also create a window will cause some bugs. You should still add in any initialization code thats required for setup before that line.
When testing a view controller it is important to specify what class is being tested. Lets say I have a controller called FooController, the corresponding spec file would look like so:
describe “The 'FooController'” do
tests FooController
#Your specs go here.
end
The tests FooController
line tells Bacon what class is actually being tested. This will instantiate a new window and new instance of the specified class. These are then available in the specs as controller
and window
. So that means I could do something like this:
describe ProjectsScreen do
tests ProjectsScreen
it "is the right class" do
controller.should.be.kind_of ProjectsScreen
end
it "does contain a table view" do
controller.tableView.should.not == nil
end
it "does display projects" do
controller.tableView.visibleCells.should.not.be.empty
end
describe "Selecting a project" do
before do
@project = controller.projects[0]
tap "#{@project.name}"
end
it "opens the projec_screen when a selection is made" do
controller.project_screen.parent_screen.should == controller
end
it "passes though the selected project" do
controller.project_screen.current_project.should == @project
end
end
end
One can override the controller by doing something like
describe ProjectsScreen do
tests ProjectsScreen
def controller
@controller ||= ProjectsScreen.new(nav_bar: true)
end
#specs
end
However, the problem here is if any of your specs push stuff onto the screen then you will get a warning saying that the view is not in the window hierarchy. This makes total sense… In the obove example the controller now returns a new ProjectScreen which is totally on its own, isolated from the app.. It hasn’t been added onto any view that is some how linked to the window.
Before I knew how the previously mentioned stuff worked I had tried crerating a new window and setting it as the key window where the object I was testing is the rootViewController.
describe ProjectsScreen do
tests ProjectsScreen
def controller
projectsScreen = ProjectsScreen.new(nav_bar: true)
window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
window.rootViewController = projectsScreen
window.makeKeyAndVisible
@controller ||= projectsScreen
end
#specs
end
However this doesn’t change a thing and messes up other things. So to stay safe. Just do it the way I mentioned above.