I'm using Nocilla to stub HTTP requests and it is working ok. I can stub the requests, return json fixtures and assert over it. The problem is that the application runs when the test starts and some requests are made on the viewDidLoad of the first view controller which cause an exception on Nocilla. How I can prevent the application from running since I only want the test code to be executed?
PS: I don't want to stub all the requests because I'm testing them!
I managed to find the solution. These kind of tests should be run in logic tests target instead of application test target which uses the application. More documentation of the differences and how to create a logic test target can be found here.
Related
I am new to unit tests in Xcode and Swift and have some trouble to understand the life cycle of XCTestCase.
How/where to add setup code which is executed before the actual app is launched?
Problem is, that first the host app is launched before any of the test setup methods (class func setUp(), func setUp(), func setUpWithError()) are executed.
It is even possible to run test code before the host app launches?
Details:
As described in a previous question my app uses a SQLite database to persist some data. When the app launches a database connection is created and data is read from the database.
To make tests consistent and repeatable I would like to use a fresh database with some well defined data every time a run the test. To archive this I tried to override setUpWithError remove the existing db file and move a file with pre-defined data in place instead.
Unfortunately this does not work, because setUpWithError is executed only after the host app was launched. The same is true for all other test setup methods.
Moving a fresh database file in place before running the tests is only an example. The problem is the same for all local data which should be in place before the host app launches to ensure repeatable tests.
An answer to my previous question included a UIApplication extension with a isTesting method which can be used to check if a test is performed. While I could use this in my app code to setup the test data, I would consider this a bad solution. I would like to keep the code completely separated from the production code. Is this possible?
There are several approaches to set up data before running a test case
NSPrincipalClass
As described here you can create a class, and the init method of that class is executed before running any test. This helps setting up dependencies used by many test cases. I don't think this is the way to go in your case.
isTesting
Instead of setting up the code in your app target, you can also check for isTesting early in the didFinishLaunchingWithOptions method of your AppDelegate and simply return there. In this case the regular code is not executed and you can run you custom database setup code in the setup of your test class.
Dependency Injection
Right now you are doing integration testing in my opinion. If you want to have proper unit tests, they should not operate against the database of the underlying app. Instead create an extra (in memory) database and inject that into the code you are testing. I think this is the way you should follow. The benefits are
Your app is not affected by your tests. Next time you start the app to manually test, your original data is still there.
Your unit tests are not affected by manual changes to the app
Your unit tests are also independent of each other. Order of execution doesn't change the results when setting up the database fresh for each test case.
It is even possible to run test code before the host app launches
If you have to ask that, your tests are not unit tests. Unit tests test code, not the app. A test that requires the app to be running would be a UI test.
In fact, the best approach for unit tests is to put all your testable code into a framework and give the framework unit tests; that way, your tests run much faster because the app never has to launch at all.
It sounds to me like the problem lies deeper in your app's code: you have evidently not written your code in such a way as to be testable. So that would be your first move. Writing testable code, and writing unit tests, is an art; you have to separate out the "system under test", which should be your code alone, and make sure you are not testing anything that doesn't belong to you and whose workings are already known — like Core Data.
I'm writing an iOS app with Swift, and we are using Parse for our backend. I'm working on some acceptance tests, and have mocked the Parse API using OHHTTPStubs.
I'm writing a test that taps through our login form and logs in a given user. In the view controller, we are calling the PFUser.logInWithUsernameInBackground function. Inside the completion block, I'm calling println(PFUser.currentUser()), and I can see that it is set correctly.
However, when I call println(PFUser.currentUser()) from my test case, it is still nil. I want to make sure that the user is being signed in, and that their username is correct.
The tests are application tests which are injected into the host application, and are written with KIF. So I think the tests may contain their own separate PFUser singleton instance, instead of accessing it on the host application. So I need to figure out how to gain access to the currentUser() inside the main app.
Is there any way I can tell my tests to use the PFUser class from the main app?
If you think this should normally work out of the box, what kind of mistakes should I look for in my code? (e.g. bridging headers, build settings, etc.)
I figured out the solution. I needed to access the class from the main bundle, and I did so by adding this line to a helper file in my test target:
let AppUser: AnyClass! = NSBundle.mainBundle().classNamed("PFUser")
This lets me perform checks such as AppUser.currentUser() == nil, and call functions like AppUser.signOut() on the main bundle, instead of in the test bundle.
The reason is that the main bundle and test bundle are separate, and classes are not shared between them. This OHHTTPStubs wiki page goes into more depth about the difference between hosted and non-hosted tests in Xcode.
I am having trouble in understanding how can I check the logs for a test inside of an engine.
So My setup is the typical example, with a main app and engine. Inside of the engine I have a dummy application(inside the rspec folder) that I use to test my engine.
Now I am construction a lib file and would like to test it. This lib is a communication system to an API and I am getting problems when communicating but it's weird since I have another application making the same requests to the same API and it works. So I wanted to check the logs for the tests(so I can see the request and the messages being passed to the API).
My first thought was to look for a log folder at the engine, which does not exist???
second I thought maybe the main application(just to clear that out of the way), obviously the logs there were not logging anything.
Then I thought it could make sense if the dummy application had some logs and it does. The test.log, but that does not log anything.
Now just as detail, I am running my tests with guard & rspec.
let me know if you have some light on this or any other thoughts that could help.
all the best,
Andre
I'm trying to use DRT for running acceptance tests.
Because it's an acceptance test I need to change the location to open the page under test. But of course, after I've done it my test script is gone.
I tried to use iFrames as a workaround, but Dart doesn't provide any means of getting the content of an iFrame. Which means that it's possible to load the page under test into an iframe, but it's impossible to get its html.
I've checked all the DRT tests in the Dart repo:
http://code.google.com/p/dart/source/browse/#svn%2Fbranches%2Fbleeding_edge%2Fdart%2Ftests%2Fhtml
but it seems that none of them changes the location.
Is it possible to use DRT for running acceptance tests? Is there a workaround I didn't think of?
We haven't come up with a good trick (redirection or iframes) to load the app as it is written and runs the test code on top of it. Instead, you could copy the entrypoint of an app and include the test code there, then run the modified app directly in DRT.
Here is an example from the web-ui codebase of a test that does this. This test runs the TodoMVC app and interacts with it:
https://github.com/dart-lang/web-ui/blob/master/test/data/input/todomvc_listorder_test.html
All we did is copy the original app's html, add the 'testing.js' script tag, and replace the dart script tag with the test code. It might be possible to create a script that automates what we do manually today, but we haven't done that.
When I run a simple functional test to get (for example) the users/signIn page, I'm getting this:
<html><head><meta http-equiv="refresh" content="0;url=https://localhost/index.php/users/signIn"/></head></html>
and then the functional test just stops. It happens in other functional tests too, but not on every request. Other tests will run fine, then when it gets to a certain request in the test, it will get that response (with the requested URL in the content attribute), and stop.
Any ideas on why this might be happening?
These functional tests used to work, but I just got this project back from another development company and I don't have an idea of where to start looking for the changes. Of course I can do diffs on the files with the version control, but I don't know where to start. Thanks for any leads!
Argh, found it quicker than I thought.
The SSL filter was turned on, and needs to be disabled for the test environment. They had removed the test environment from app.yml.
test:
disable_sslfilter: true