2013-07-30 3 views
0

У меня есть сомнения относительно тестирования частных/защищенных методов. Это общий вопрос, который касается модульного тестирования для любой платформы. Но просто для того, чтобы сказать вам, я работаю с phpunit платформой для модульного тестирования php.Должен ли я тестировать частные/защищенные методы? Зачем?

Должны ли мы тестировать частные/защищенные методы? Принятый ответ на этот question говорит, что мы обычно не должны. Из этого ответа:

Обычно вы просто не испытываете или издеваться частная & защищенных методы directy.

Что вы хотите проверить, это публичный API вашего класса. Все остальное представляет собой детальную реализацию для вашего класса и показывает, что вы не «ломаете» ваши тесты, если вы ее измените.

Но в то же время другие ответы по многим вопросам дают возможность их протестировать (я предполагаю, что эти ответы означают, что мы должны тестировать частные/защищенные методы, поскольку они не говорят, что мы должны или не должны их тестировать).

Пожалуйста, объясните причину. Спасибо.

+0

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

+0

Есть много вопросов (и ответов) о SO о том, как сделать не ту вещь ... :) –

+0

@ DuncanJones Ok. Затем я прошу вас предложить мне, что делать, если у меня есть это сомнение. – Geek

ответ

1

Что касается меня - это зависит от сложности частных/защищенных членов.

Например у вас есть частные методы Func1() и Func2() со сложным вычислением или алгоритмы с большим количеством входных параметров. И у вас есть общедоступный API, который использует их оба. А по некоторым данным Func1() разбит и возвращает неверные данные, но во время обработки в Func2() эти данные каким-то образом преобразуются в правильный результат (в результате другой проблемы). Итоговый результат общедоступного API-метода будет правильным - это означает, что ВЫ НЕПРАВИЛЬНО Func1 и Func2, но ваш API-интерфейс исправляет как-то. И вы это проверите, и все в порядке.

Теперь вы дали вам код кому-то, и он/она создала FUNC3() и еще один публичный метод API, который использует FUNC1() и FUNC3() и модульного тестирования для этого метода API не удается. Сколько времени он потратит, чтобы узнать, что причина в Func1? И когда Func1 будет исправлен, у вас будет предыдущий тест с Func2 сбой ... Это общее нехорошо.

Итак, ИМХО вам следует проверять частные/защищенные методы, если они сложны (много кода или использования не очевидного algo) и могут использоваться повторно. И, конечно, вам не нужно создавать 100 единичных тестов для частного метода, который возвращает + b или записывает запись журнала отладки.

Надеюсь, мой ответ вам поможет! С уважением, Михаил.

0

Я считаю, что тестирование частных/защищенных методов зависит от того, где/как они доступны, и что тестируется.

Если я создаю многоразовую библиотеку общего кода, тогда частные и защищенные методы в этих классах проверяются в рамках тестовых примеров библиотеки.Эти тесты гарантируют, что код нижнего уровня работает, чтобы я мог верить в библиотеку.

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

Бизнес-приложение не пытается проверить частные/защищенные методы библиотеки, поскольку я считаю, что черный ящик кода, о котором я не знаю (похож на внешнюю библиотеку или веб-службу). Тем не менее, я проверяю частные и защищенные методы бизнес-приложения в наборе тестов для бизнес-приложения, чтобы убедиться, что методы/функции ведут себя так, как должны.

В качестве примера то, предположим следующие бизнес-классы (очень кратко передать мысль, а не функции):

<?php 
class ACCOUNTS 
{ 
    protected GetEstimation() 
    { 
     ... 
     return $CalculatedValue; 
    } 
} 

class CUSTOMER_ACCOUNT extends ACCOUNTS 
{ 
    protected GetEstimation() 
    { 
     $BaseEstimation = parent::GetEstimation(); 
     ... 
     return $NewCalculatedValue 
    } 
} 

class RESELLER_ACCOUNT extends ACCOUNTS 
{ 
    protected GetEstimation() 
    { 
     ... 
     return $ResellerCalculatedValue; // Note: No call to parent 
    } 
} 
?> 

В этом примере существуют различные значения, которые будут возвращены. Была использована функция Protected, поэтому ее можно было переопределить, и она не должна полагаться на функциональность родительского класса. В этом примере я хочу протестировать все эти классы, возвращая правильные значения, когда они используются.

Базовый класс ACCOUNTS должен возвращать оценку после выполнения своих вычислений на основе значений класса. Как правило, я просто установить значения и проверить возвращения:

<?php 
class ACCOUNTSTest extends PHPUnit_Framework_TestCase 
{ 
    protected $Accounts; 

    protected function setUp() 
    { 
     $this->Accounts = new ACCOUNTS(); 
    } 

    public function testEstimationHome() 
    { 
     $this->Accounts->InternalValue1 = 1; 
     $this->Accounts->InternalValue2 = 10; 
     $this->Accounts->InternalValue3 = 100; 
     $this->assertEquals(523, $this->Accounts->GetEstimation(), 'Test Home Account with values 1, 10, 1000'); 
    } 

    public function testEstimationHome2() 
    { 
     $this->Accounts->InternalValue1 = 5; 
     $this->Accounts->InternalValue2 = 2; 
     $this->Accounts->InternalValue3 = 10; 
     $this->assertEquals(253, $this->Accounts->GetEstimation(), 'Test Home Account with values 5, 2, 10'); 
    } 

    protected function tearDown() 
    { 
     unset($this->Accounts); 
    } 
} 
?> 

Эти тесты теперь гарантировать, что ACCOUNTS-> GetEstimation() работает правильно. Затем я тестировал CUSTOMER_ACCOUNT и имел аналогичные тесты, чтобы убедиться, что класс правильно вычисляет.

Да, если базовый класс изменяется, тогда мне может потребоваться обновить тесты в CUSTOMER_ACCOUNT, поскольку ACCOUNTS-> GetEstimation() изменен, но у меня также есть дополнительная проверка, что базовый класс все еще корректно возвращается.

В качестве альтернативы я мог бы изменить эту структуру и использовать Injection Dependency для предоставления определенной информации (ACCOUNTS), чтобы гарантировать, что если родительская оценка всегда была 523, тогда этот класс возвращает правильные значения. Если ACCOUNTS изменяет полученную оценку, и это не имеет значения для этого класса (возможно, этот класс просто добавляет дополнительные значения), тогда я изолирую свой тест и не нуждаюсь в беспокойстве.

Надеюсь, это обновление поможет проиллюстрировать то, что я говорю.

+0

Благодарим вас за ответ. Я понимаю, почему нам не нужно тестировать библиотеку. Но можете ли вы уточнить, почему мы должны тестировать частные/защищенные методы бизнес-приложения? – Geek

+0

Бизнес-приложение по-прежнему нуждается в работе. В целом ряде классов приложений используется Private/Protected, поэтому внешние классы не могут изменять значения. Однако, если я выполняю нетривиальную работу в методе класса (и он может быть закрытым), я хочу убедиться, что класс проверен и этот метод не изменяется. Я написал псевдо пример в качестве ответа, чтобы помочь объяснить это. –

1

Частные и защищенные методы - это детали реализации тестируемого кода и не должны проверяться. В ваших тестах говорится, «что» должен делать ваш код. Тестирование частных и защищенных методов начинает зависеть от того, как ваш код должен делать то, что он делает.

Когда вы модифицируете свой класс, чтобы добавить некоторые частные методы, потому что вы нашли повторное использование кода, и у вас возникли неудачные тесты, потому что вы изменили некоторые функции и вам нужно исправить этот тестовый пример. Если у вас есть тесты для частных и защищенных методов, и вы делаете то же самое сейчас, вам нужно выяснить, не прошли ли тесты по уважительной причине или от вашего повторного факторинга. Частные и защищенные методы покрываются с помощью тестов для открытого интерфейса класса и не нуждаются в каких-либо тестах.

Просто потому, что вы «можете» что-то сделать, это не значит, что вы «должны» что-то делать.

Когда я тестирую, я считаю, что тестируемая система является черным ящиком. Я что-то даю, и я ожидаю, что что-то произойдет.Меня не волнует, что происходит внутри. Все, что важно, это то, что задан правильный вывод.

Сложные внутренние функции - это запах кода, возможно, у меня есть класс, который слишком много работает, и, возможно, у него есть другой класс.

Смежные вопросы