Вы явно проводите модульное тестирование частного метода, когда используете свои знания частного метода для выбора тестовых случаев - PullRequest
3 голосов
/ 28 сентября 2010

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

/**
 * Returns the base name of the output generator class. If the class is named
 * Reno_OutputGenerator_HTML, this would return "HTML".
 *
 * @return string
 */
protected function getName()
{
    $class = get_class($this);
    $matches = array();

    if (preg_match('/^Reno_OutputGenerator_(.+)$', $class, $matches))
    {
        return $matches[1];
    }
    else
    {
        throw new Reno_OutputGenerator_Exception('Class name must follow the format of Reno_OutputGenerator_<name>.');
    }
}

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

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

(Кстати: если вам интересно, почему существует такой странный метод, он используется для автоматического определения, в каком каталоге хранятся файлы шаблонов этого класса).

Ответы [ 2 ]

2 голосов
/ 28 сентября 2010

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

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

Итак, нет, я не вижу в вас странного. Метод может оставаться внутренним, и вы можете добавить дополнительный контрольный пример - вам, вероятно, нужен только один с исключением, верно?

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

0 голосов
/ 28 сентября 2010

Вы также можете протестировать эту функцию, выведя из класса в вашем тестовом классе, как это:

namespace TheProject
{
    public class ClassUnderTest
    {
        protected string GetName()
        {
            return "The name";
        }
    }
}

namespace TestProject
{
    [TestClass]
    public class TheTest:TheProject.ClassUnderTest
    {
        [TestMethod]
        public void TestGetName()
        {
            string expected = "The name";
            string actual = GetName();
            Assert.AreEqual(expected, actual);
        }
    }
}

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

...