OCUnit в XCode 4.5 для новичков

от автора

Однажды мне надоело, что исправление багов занимает у меня больше времени, чем разработка приложения, и в поисках путей решения я пришел к TDD — Test-driven development (Разработка через тестирование).

В это статье рассказывается как делать первые шаги в XCode 4.5, используя unit test-ы, при разработки приложений под IOS.

Статья предназначена для новичков, в ней не содержится информации для зубров разработки.

Введение

Начнем с самого начала, создадим новый проект, отметим галочку «Include Unit Tests» и назовем его Ocu:
file -> new -> project -> single view application
step 1
Я предпочитаю не использовать ARC, так как придерживаюсь правила, что новые фичи должны полежать пока их не доведут до ума, а он появился всего год назад. Да и ручное управление памятью не такая уж сложная штука, и небольшая практика в этом будет полезна.

Мы создали проект в который включен фреймворк SenTestingKit, этот фреймворк и будет нам помогать.
В проекте видим 2 группы — Ocu и OcuTests, в первой содержится код нашего прилложения, во второй юнит тесты.
step 2

Откроем файл «OcuTests.m» и найдем метод «testExample».
OcuTests.m

#import "OcuTests.h"  @implementation OcuTests  - (void)setUp {     [super setUp];          // Set-up code here. }  - (void)tearDown {     // Tear-down code here.          [super tearDown]; }  - (void)testExample {     STFail(@"Unit tests are not implemented yet in OcuTests"); }  @end 

setUp — это метод который выполнится перед началом тестирования, тут можно инициализировать все объекты, которые нам понадобятся для теста.
tearDown — это метод который выполнится после окончания тестирования, тут можно уничтожить все использованные нами объекты.
testExample — это самый первый тест, который мы выполним, он содержит простой макрос который вызовет сообщение об ошибке и напишет, что мы еще не создали ни одного юнит теста.

Вообще, если название метода начинается на test и он возвращает void, то SenTestingKit автоматически распознает его как тест и выполнит.

Запустим тест (нажатием «cmd+U» или нажав на кнопку «Run» и подержав ее, выбираем из выпавшего списка «Test») и посмотрим что нам напишет дебаггер.

Test Suite 'OcuTests' started at 2012-11-22 22:27:01 +0000. Test Case '-[OcuTests testExample]' started. /Ocu/OcuTests/OcuTests.m:29: error: -[OcuTests testExample] : Unit tests are not implemented yet in OcuTests Test Case '-[OcuTests testExample]' failed (0.000 seconds). Test Suite 'OcuTests' finished at 2012-11-22 22:27:01 +0000. Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.000) seconds 

Дебаггер написал что выполнен 1 тест, и тест не пройден, и выдал нам описание которое мы поставили в макросе.

Теперь мы знаем где писать тест, как его запустить и где посмотреть результат выполнения. Приступим к написанию самого простого теста.

Пример 1 — проверка сложения

В этом примере мы просто создадим 2 переменные и проверим результат их сложения.

Определим 2 переменные, которые будем складывать, и метод в котором будет содержаться наш тест.
OcuTests.h

#import <SenTestingKit/SenTestingKit.h>  @interface OcuTests : SenTestCase {     float foo;     float bar; }  - (void) testMathAdd;  @end 

В методе setUp проинициализируем переменные и присвоим им значение, а в методе testMathAdd проверим результат сложения.
OcuTests.m

- (void)setUp {     [super setUp];          foo = 2.0;     bar = 5.0; }  - (void)tearDown {     // Tear-down code here.          [super tearDown]; }  - (void) testMathAdd {     STAssertTrue (foo + bar == 6.0, @"%f + %f should be 7.0", foo, bar); } 

Запускаем тесты «cmd+U» и видим сообщение об ошибке с комментарием.

Test Suite 'OcuTests' started at 2012-11-23 12:26:14 +0000 Test Case '-[OcuTests testMathAdd]' started. /Ocu/OcuTests/OcuTests.m:30: error: -[OcuTests testMathAdd] : "foo + bar == 6.0" should be true. 2.000000 + 5.000000 should be 7.0 Test Case '-[OcuTests testMathAdd]' failed (0.000 seconds). Test Suite 'OcuTests' finished at 2012-11-23 12:20:42 +0000. Executed 1 test, with 1 failure (0 unexpected) in 0.000 (0.000) seconds 

В комментарии указано что результат сложения отличается от ожидаемого, исправим ошибку.
OcuTests.m

- (void) testMathAdd {     STAssertTrue (foo + bar == 7.0, @"%f + %f should be 7.0", foo, bar); } 

Запускаем тест и видим сообщение о том, что тест пройден.

Test Suite 'OcuTests' started at 2012-11-23 12:26:14 +0000 Test Case '-[OcuTests testMathAdd]' started. Test Case '-[OcuTests testMathAdd]' passed (0.000 seconds). Test Suite 'OcuTests' finished at 2012-11-23 12:26:14 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.000 (0.000) seconds 

Пример 2 — вычисление значения свойства объекта

В этом примере мы создадим объект, присвоим значения его свойствам и проверим правильно ли создалость еще одно свойство.

Добавим в проект новый класс — выбираем шаблон «Objective-C class» и выбираем «Subclass of NSObject», вводим название «Triangle», при сохранении отмечаем галочкой «Targets OcuTests». В итоге в группе OcuTests получаем 2 новых файла «Triangle.h» и «Triangle.m».
В них создаем необходимые методы.

Triangle.h

#import <Foundation/Foundation.h>  @interface Triangle : NSObject {     float cathetus1;     float cathetus2; }  - (id)initWithCathetus1:(float)cat1 andCathetus2:(float)cat2; - (float)getHypotenuse;  @end 

Triangle.m

#import "Triangle.h"  @implementation Triangle  - (id)initWithCathetus1:(float)cat1 andCathetus2:(float)cat2 {     cathetus1 = cat1;     cathetus2 = cat2;          return self; }  - (float)getHypotenuse {     float hypotenuse = hypotf(cathetus1, cathetus2);     return hypotenuse; }  @end 

И соответственно делаем изменения в тестах.
OcuTests.h

#import <SenTestingKit/SenTestingKit.h>  @interface OcuTests : SenTestCase  - (void)testTriangleHypotenuse;  @end 

OcuTests.m

#import "OcuTests.h" #import "Triangle.h" // добавляем новый класс, который будем тестировать  @implementation OcuTests  - (void)setUp {     [super setUp]; }  - (void)tearDown {         [super tearDown]; }  - (void)testTriangleHypotenuse {     float cat1 = 3.0;     float cat2 = 4.0;     Triangle *tri = [[Triangle alloc] initWithCathetus1:cat1 andCathetus2:cat2];          STAssertTrue([tri getHypotenuse]==5.0, @"Hypotenuse should be 5.0 with catheti: %f, %f", cat1, cat2);              [tri release]; } 

Выполняем тест и получаем сообщение о пройденном тесте.

Test Suite 'OcuTests' started at 2012-11-23 14:25:39 +0000 Test Case '-[OcuTests testTriangleHypotenuse]' started. Test Case '-[OcuTests testTriangleHypotenuse]' passed (0.000 seconds). Test Suite 'OcuTests' finished at 2012-11-23 14:25:39 +0000. Executed 1 test, with 0 failures (0 unexpected) in 0.000 (0.000) seconds 

PS:
Если вам будет интересно прочитать следующую статью, то напишите, пожалуйста, какие примеры для тестирования вы хотели бы увидеть.

ссылка на оригинал статьи http://habrahabr.ru/post/159985/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *