Работа с TDD / Unit-Testing усталость - PullRequest
7 голосов
/ 08 августа 2010

Так что я привыкаю к ​​TDD, но столкнулся с неожиданной проблемой: я очень устал от 100% покрытия кода. Написание тестов становится более утомительным, чем сам код, и я не уверен, правильно ли я это делаю. Мой вопрос: Какие вещи вы должны тестировать, и какие вещи излишни?

Например, у меня есть следующий тест, и я не уверен, что он полезен вообще. Что мне делать, чтобы я все еще следовал TDD, но не уставал писать тесты?

describe 'PluginClass'

    describe '.init(id, type, channels, version, additionalInfo, functionSource, isStub)'

        it 'should return a Plugin object with correct fields'

            // Create test sets
            var testSets = new TestSets()
            var pluginData = {
                'id'                : null,
                'type'              : null,
                'channels'          : null,
                'version'           : null,
                'additionalInfo'    : null,
                'functionSource'    : null,
                'isStub'            : true
            }
            testSets.addSet({ 'pluginData' : pluginData })
            var pluginData = {
                'id'                : "testPlugin1",
                'type'              : "scanner",
                'channels'          : ['channelA', 'channelB'],
                'version'           : "1.0",
                'additionalInfo'    : {'test' : "testing"},
                'functionSource'    : "function () {alert('hi')}",
                'isStub'            : false
            }
            testSets.addSet({ 'pluginData' : pluginData })

            for (var t = 0; t < testSets.getSets().length; t ++) {
                var aTestSet = testSets.getSet(t)

                var plugin = new Plugin().init( aTestSet.pluginData.id,
                                                aTestSet.pluginData.type,
                                                aTestSet.pluginData.channels,
                                                aTestSet.pluginData.version,
                                                aTestSet.pluginData.additionalInfo,
                                                aTestSet.pluginData.functionSource,
                                                aTestSet.pluginData.isStub  )

                plugin.getID().should.eql aTestSet.pluginData.id
                plugin.getType().should.eql aTestSet.pluginData.type
                plugin.getChannels().should.eql aTestSet.pluginData.channels
                plugin.getVersion().should.eql aTestSet.pluginData.version
                plugin.getAdditionalInfo().should.eql aTestSet.pluginData.additionalInfo
                eval("fn = " + aTestSet.pluginData.functionSource)
                JSON.stringify(plugin.getFunction()).should.eql JSON.stringify(fn)
                plugin.getIsStub().should.eql aTestSet.pluginData.isStub
            }

        end

    end

end

Ответы [ 6 ]

7 голосов
/ 08 августа 2010

Конечно, вышеприведенный «тест» во многих отношениях является излишним.Он слишком длинный и сложный, трудно читаемый и утверждает слишком много вещей.Я не могу себе представить, как это могло произойти из процесса TDD.Неудивительно, что вы устали от подобных вещей ...

Разработка, основанная на тестировании, означает: вы должны идти детскими шагами, где каждый шаг является отдельным тестом, утверждает только одну вещь и содержит абсолютнонет логики (то есть нет for, if/else или подобный ...).Таким образом, приведенный выше код приведет к примерно 4-6 отдельным методам тестирования, которые вы затем реализуете один за другим.Сначала подтвердите правильную инициализацию свойства (с другими требуемыми значениями), затем убедитесь, что методы работают должным образом, и так далее ...

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

В итоге: тестирование практически для всего не является чрезмерным (100% охвата), но, безусловно, проблема в том, чтобы иметь тесты, как в вашем примере.

Я рекомендую вам ознакомиться с практикой тестирования TDD / unit-тестов, Книга "Art Of Unit Testing" может бытьхороший ресурс ...

HTH!Томас

3 голосов
/ 08 августа 2010

Одна вещь, которую я думаю, что люди забывают, это то, что с автоматическим модульным тестированием это все еще практика кодирования.Вполне приемлемо настроить шаблонные / универсальные классы, базовые классы, вспомогательные классы или любые другие обычные шаблоны разработки программного обеспечения, с которыми вы знакомы, для проведения модульного тестирования.Если вы чувствуете, что делаете одно и то же снова и снова, вы, вероятно, есть!Это признак того, что ваш мозг говорит вам: «Есть лучший путь».

Так что дерзайте.

2 голосов
/ 08 августа 2010

Целью модульного тестирования должно быть тестирование частей кода, которые могут содержать ошибки. Достижение 100% покрытия тестами не должно быть целью, и AFAIK, TDD не называет это целью.

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

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

1 голос
/ 11 августа 2010

Ваш тест пытается проверить слишком много вещей одновременно.Разделите его на несколько тестов и проведите рефакторинг своего тестового кода (да, вспомогательные методы разрешены).

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

0 голосов
/ 28 марта 2017

Усталость, лень и апатия - наш естественный инстинкт, позволяющий избегать бессмысленной работы, такой как написание тривиальных тестов, что, вероятно, имеет место. Попробуйте прекратить юнит-тестирование тривиальных вещей, и вы сразу почувствуете себя лучше.

Ваш конкретный тест далеко не сложен. Я участвовал в качестве рецензента кода во многих проектах с тысячами модульных и интеграционных тестов, и все же я видел проект, в котором тесты было бы легче читать и понимать, чем реальный живой код. Удобочитаемость TDD, «тест как документация» и подобные обещания просто не соответствуют действительности. Это легко доказать - попробуйте освоить новую кодовую базу, читая только тесты или читая только живой код. Какой способ является более всеобъемлющим? Правильно разработанный живой код обеспечивает полную и целостную картину компонента, в то время как тесты представляют собой лишь фрагментированные утверждения об этом.

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

0 голосов
/ 09 августа 2010

Кажется, вы

  • тестируете конструкторы с простым назначением членов.Это излишне, если в конструкторе нет какой-то нетривиальной логики.Вместо этого положитесь на это, чтобы пройти тестирование в рамках некоторых других тестов, где члены будут использоваться.
  • сравнение равенства между двумя объектами значения.Переопределите / определите проверку на равенство для типа / класса плагина, переопределив метод equals.поэтому plugin.should.eql expected_plugin должно быть единственным утверждением
  • также рассмотрите возможность использования вспомогательных объектов для построения сложных тестовых данных.
...