Как я могу написать модульный тест, который проверяет, что мои свойства выпущены в dealloc на iOS? - PullRequest
2 голосов
/ 28 апреля 2011

Я довольно новичок в TDD и модульном тестировании, и я попробую в стороннем проекте.

И я застрял в модульном тестировании метода dealloc.

Мы все знаем, что это хорошая практика - освобождать пользовательские свойства и устанавливать их в nil в dealloc:

-(void) dealloc{
  [myProperty release];
  myProperty = nil;
  [super dealloc];
}

Как я могу написать модульный тест, который проверяет это поведение?

Очевидно, это не работает:

[myObject release]
STAssertNil(myObject.myProperty,@"myProperty should be released and set to nil in dealloc")

Есть предложения? спасибо!

Ответы [ 2 ]

4 голосов
/ 28 апреля 2011

Предполагая, что вы могли бы сделать выше, что вы на самом деле будете тестировать? Вот что я думаю:

  1. проверка того, что -релиз уменьшает значение retainCount

  2. проверка того, что когда retainCount достигает нуля, механизм сбора мусора NSObject вызывает -dealloc

  3. проверка того, что при вызове -dealloc освобождается myProperty

Это неправильная гранулярность для модульного теста, пункты один и два - не ваше дело проверять - предположим, что это яблочный тест. Итак, единственное из вышеперечисленного, которое является модульным тестом:

проверка, когда вызывается -dealloc, myProperty выпущен

Теперь этот кусок кода (совершенно справедливо) не имеет никакой логики и не производит никакого вывода. Итак, я считаю, что модульное тестирование на самом деле параноидально и необычно (похоже на тестирование того, что компилятор действительно работает).

Но если бы я захотел проверить это, я бы сделал это так:

OCMockObject *mockProperty = MOCK(NSObject);
[[mockProperty expect] release];
myObject.myProperty = mockProperty;
[myObject dealloc];
[mockProperty verify];

Очевидно, что вы никогда не должны напрямую вызывать -dealloc, но если вы хотите выполнить модульный тест -dealloc, это именно то, что вы должны делать (или это не модульный тест). Учитывая, что это крайне плохая практика и тест приносит вам очень мало, я не думаю, что вам стоит беспокоиться.

1 голос
/ 28 апреля 2011

Это определенно избыточно для TDD. Вы хотите протестировать функциональность модуля с помощью TDD и выявить более простые ошибки с помощью другого инструмента. (Я просто беспокоюсь, что если вы начнете писать тесты с таким уровнем детализации, вы никогда не сможете завершить проект.) Я лично не считаю refcounts частью интерфейса модуля, поэтому для меня это просто выходит за рамки самого модульного теста.

Я предлагаю использовать контрольно-измерительные приборы. Запустите все свои тесты и проведите их инструментарий (в OS X мы используем приложение «Инструменты» начиная с 10.5, в Linux мы используем Valgrind). Инструментарий скажет вам, все ли ваши объекты освобождены или у вас есть утечка памяти. Я также рекомендую убедиться, что вы тестируете пути ошибок - по моему опыту, большинство утечек памяти происходит, когда другие ошибки происходят одновременно.

Я использую собственный сценарий тестирования, который проходит через все тесты, и у него есть флаг опции для их инструментирования. Я не всегда их проверяю, потому что полный уровень аппаратуры немного замедляет тестирование.

Однако, если вы хотите сделать что-то трудное:

someProp = [[... alloc] init];
assert([someProp retainCount] == 1);
[myObject setSomeProp:someProp];
assert([someProp retainCount] > 1); // NOT == 2, that would be wrong
[myObject release];
assert([someProp retainCount] == 1);

Извинения за архаику, стиль Obj-C 1.0.

...