Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone command line Unit Tests (and File I/O)

The short question is: How can I get iPhone (objective-c) file operations to work correctly from a command line Unit Test?

The long question, with explanation: This will eventually become a script to perform automated building/testing for my iPhone build, via a Hudson instance. Following makdad's link on this SO question has allowed me to run Unit tests from the command line (semi) successfully.

However, one of my tests fails. The test would call a Caching Service class to save a file, then try and retrieve it. however, file I/O appears to not work when running the tests from the command line :(.

For Reference, running the Unit tests via the Xcode GUI results in no such errors.

I am using NSFileHandle method calls to get handles for writing. if they return nil, the file is created using

[[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil]; 

I thought it may have to do with the spaces in the path to the simulator's cache directory. am I on the right track? if so, how would i rectify this?

Note also that the simulator needs to be NOT running already in order for this to work, the simulator is started programmatically and does not display a GUI. if it is running, the command line build fails.

like image 920
Robotnik Avatar asked Sep 27 '11 06:09

Robotnik


People also ask

What is XCTest in iOS?

Overview. Use the XCTest framework to write unit tests for your Xcode projects that integrate seamlessly with Xcode's testing workflow. Tests assert that certain conditions are satisfied during code execution, and record test failures (with optional messages) if those conditions aren't satisfied.

What is difference between unit tests and UI test in Xcode?

The really short version is that unit tests have access to the code in your app (or whatever kind of module you are building) and UI tests do not have access to the code. A unit test only tests one single class per test.

How do I run unit test from console?

run Visual Studio unit tests by using MSTest.exe, located at %ProgramFiles%\Microsoft Visual Studio 10.0\Common7\IDE\MSTest.exe in my case. using /testcontainer:Path\To\Your\TestProjectAssembly. dll to indicate where your tests are coded. You can specify multiple '/testcontainer' options if required.


Video Answer


1 Answers

First: 'the simulator needs to be NOT running already in order for this to work'
I have my tests running in the terminal and it doesn't matter if the simulator is on.

Maybe some build settings you have to look at are: TEST_HOST and BUNDLE_LOADER. I leave them empty in my xcodeproj.
Note: I'm using Hudson as well with test reports and code coverage.

Second:
I have experienced failures in tests terminal and application with loading paths. This was related to the Core Data model which is loaded from a resource.
The solution was to load the file from url instead of a path:

[[NSBundle bundleForClass:[self class]] URLForResource:....]; 

I cannot ensure this relates to the same problem your encountering with the NSFileManager, but i can only imagine that NSBundle makes use of the NSFileManager. (So this can be related)

Third:
Do not make your tests dependent on I/O.
I find that that is not the purpose of a Unit Test. Such test may not rely on a filesystem, database, network connection, etc.

Make an file system abstraction class that you mock while running your tests.
This way your implementation is only at one place relying on the actual file system, which you can replace during testing.

You only need one test to check that abstraction.

Summary

  • The first will improve your test setup.
  • The second will hopefully solve your test problem.
  • The third will reduce the occurrence of the problem and improve your code.

Hope this was helpful.

like image 152
Mats Stijlaart Avatar answered Sep 22 '22 19:09

Mats Stijlaart