Software and unit testing for iOS

ios_testing_mway

Software testing, also known as quality assurance (QA), on one hand should support developers in their software projects and on the other hand assure profit. For efficient Testing constraints and guidelines should be defined on how a written program should be tested.

Most developers think the results of testing software are bugs for showing that the software does not work. Bugs are usually bad, because it costs a lot of money to fix them. The result of software testing is quality assurance and not quality insertion, which means testing software should demonstrate that software works and contains all the features, which the customer expect. Testing should help the developers to improve their software in a cheap way.

When to test a software?

Generally the earlier a code part of a written software can be tested, the cheaper it will be to find potential problems in the tested code. In traditional software projects an intensive testing phase starts at the end of the project, after the development phase and before the general release. In modern software projects is the approach to test all parts of the code at all times. This is possible because agile project management is organized in sprints (iterations) and at the end of every sprint the current progress is checked and reviewed. An iOS developer should also start testing when a new device or a new iOS Version was released.

What is unit testing and what is the (personal) benefit?

Unit testing is gives developers the possibility to test their own written software. Usually they test a single „unit“ of source code in a class. So we can say that a unit test is a small piece of code, which tests the behavior of another code. Unit testing for iOS allows in the first step to define preconditions, runs in the second step the code using the preconditions under test and in the last step assertions in the final state. The test is successful, when all assertions are valid, otherwise in case of a failure, the asserted state includes an exception which stops the test. The developers use certain testing framework to write unit tests. The main advantage of unit tests is the fact that the running of the tests is automated. Means that you have to write a certain test once and as result the computer runs the test whenever and how often it is required. This behavior makes it very cheap e.g. for regression bugs: Regression bugs are bugs which had been fixed, but are reintroduced e.g. by a new developed feature. Because of unit tests it’s always possible to run the unit tests to ensure that you do not reintroduce a regression bug. Unit tests can have for iOS developers a big benefit, because the tools, which are needed to use unit tests in an iOS project are free and already integrated in Xcode. The developer himself can write the tests so there is no need to hire a QA-specialist to get the first results. On one hand time is needed to design and write the different test cases, and on the other hand the written tests helps the developer better understand his code and helps him as a result avoid bugs.

Techniques for iOS unit testing

Test-First or Test-Driven is the main paradigm of unit testing: This means that developers should be encouraged to write tests before the code, which should be tested, which results in an „acceptance criteria“ of the product: The code is good enough as soon as all defined tests were passed. The idea behind that is to keep in mind the reason for which a given code is written for.

The Red-Green-Technique is the second important paradigm, which includes three parts of unit testing: First write a test for a micro feature, which fails (red), because the code, which should be tested, does not yet exist. Then write the needed application code to get the test to pass (green). After writing the code try to clean up the code, without changing the behavior (refactor). After the implementation of the micro feature is finished, go back to red and start adding the next micro feature (requirement) to the app. The Red-Green-Technique supports iterative approach because one feature is developed after the other.

Advantages of unit testing for iOS apps

A big advantage of unit testing for iOS apps is that it is not very expensive for iOS developers to improve the quality of their apps. All the tools you need for such a test is already included in the current iOS SDK package. Another advantage is, that you can write and run the tests by yourself without hiring a QA specialist to get successful results.

Writing unit tests take very little time. Meaning that, time is only needed to design and write the test cases. As a result of the needed time the developer gets a bigger understanding, of what his iOS code does.

An iOS developer has no control over the application released to the customers, since Apple covers this task. If an application has a serious bug in the released version, after fixing this bug in the next version, the developer has to wait for Apple to approve the update to the Apple app Store. Unit testing for iOS can avoid such bugs. So one thing is releasing bugs in software, the other is not to be in a position of rapidly releasing the fixed bugs.

Overview of available testing-frameworks for XCode

The following table shows a short overview over available unit testing frameworks:

Framwork XCode Runs on: Debugging Notes
XCTest Best Both Good Built-into Xcode 5
OCUnit Best Simulator Good Built-into Xcode
GHUnit Add-on Both Good Separate build target
Expecta Good Both Good Matchers, supports async
OCHamcrest Good Simulator Good Matchers
Kiwi Good Simulator Difficult? Blocks run on OCUnit

XCTest is fully integrated in the XCode 5. OCUnit is fully integrated in XCode lower than Version 5. GHUnit is an add-on and uses a separate build target. As result you can run unit tests on the device or on simulator.

Assertions in XCTest

The following assertions are used in XCTest. This list is essentially the same as the list of assertions supported by SenTestingKit, but with the “ST” prefix changed to “XCT”. An assertion is a predicate (a true–false statement) placed in a test-case to indicate that the developer thinks that the predicate is always true at that place. Assertions are needed to describe test-cases in iOS unit tests:

  • XCTFail (format…)
  • XCTAssertNil (a1, format…)
  • XCTAssertNotNil (a1, format…)
  • XCTAssert (a1, format…)
  • XCTAssertTrue (a1, format…)
  • XCTAssertFalse (a1, format…)
  • XCTAssertEqualObjects (a1, a2, format…)
  • XCTAssertEquals (a1, a2, format…)
  • XCTAssertEqualsWithAccuracy (a1, a2, accuracy, format…)
  • XCTAssertThrows (expression, format…)
  • XCTAssertThrowsSpecific (expression, specificException, format…)
  • XCTAssertThrowsSpecificNamed (expression, specificException, exceptionName, format…)
  • XCTAssertNoThrow (expression, format…)
  • XCTAssertNoThrowSpecific (expression, specificException, format…)
  • XCTAssertNoThrowSpecificNamed (expression, specificExcepton, exceptionName, format…)

A simple example with XCTest

(void)testThatTopicExists {
Topic *newTopic = [[Topic alloc] init]; XCTAssertNotNil(newTopic,
@"should be able to create a Topic instance");
}

This is a very simple example of a test case. The test case checks under usage of the assertion XCTAssertNotNil that a specific topic exists:

(void)testThatTopicCanBeNamed {
Topic *namedTopic = [[Topic alloc] initWithName: @"iPhone"]; STAssertEqualObjects(namedTopic.name, @"iPhone",
}
@"the Topic should have the name I gave it");

This test case shows that a topic can have a name. In this example the topic has the name „iphone“.

Conclusion

Apple delivers in his latest XCode-Version all needed features in the XCTTest framework (in earlier Xcode Version OCUnit framework) to create full-featured apps using Test Driven Developement. For an iOS developer it is very easy to start with Test Driven development, because everything is already integrated in XCode, but the TDD integration in XCode is not the cutting edge of todays software engineering. With this big toolbox iOS developer can write and ship apps with a high quality.

4 thoughts on “Software and unit testing for iOS

  1. Mike Elets

    I normally don’t comment on articles, but this one is misleading and in some cases just wrong. I’m only going to point out the few high level items to make other readers aware that they should continue their research. I tried to get additional information on your creditionals but I could not find any.

    First a regression bug is NOT one that has been fixed and then is broken again by future code. It is in-fact a bug that appears when working code stops working due to future code. Minor distinction, but important.

    More importantly you imply that unit tests are “not very expensive”. Based on what metric? A typical unit test is about 2-3 times the size of the code it’s testing if you’re making sure to cover both your happy path and a reasonable number of unhappy path situations. This increases development time by a like amount, making unit tests very expensive. This may be desirable on some projects, but it needs to be considered. In addition, refactoring highly covered code can be even more time consuming as you’ll need to refactor any failing test as well (after evaluating why the test is failing, is it a dated tests or bad code).

    As for your tutorial on how to write tests – although technically correct, it does lead to another problem. Most developers do not know how to write good tests or don’t have the time to write good test due to other deadlines. In your example you’re testing pointless code. Getter and setters need not be tested, it’s pointless as they are extreamly unlikely to fail (unless they have side effects) and will be caught in any real test later.

    Again, this is just a warning to anyone that may have found this post – keep researching.

    Reply
  2. Pingback: Common Challenges of Mobile App Testing | Business First Family

  3. Pingback: Mobile App UX Creative Strategy in Action | Thinking Mobile

  4. Pingback: Software and unit testing for iOS | Intelligent...

Leave a Reply

Your email address will not be published. Required fields are marked *