Тестирование теста?

Проблема в том, что ваша грамматика оставлена ​​рекурсивной . PetitParser использует жадный алгоритм сверху вниз для разбора входной строки. Если вы выполните шаги, вы увидите, что они идут от start, а затем variable -> component -> indexed -> variable. Это становится циклом, который выполняется бесконечно, не потребляя никакого ввода , и является причиной переполнения стека (на практике это рекурсивность влево).

Хитрость для разрешения ситуации - переписать синтаксический анализатор, добавив промежуточные шаги, чтобы избежать повторения влево. Основная идея заключается в том, что переписанная версия будет использовать как минимум один символ в каждом цикле. Давайте начнем с того, что немного упростим анализатор, рефакторинг нерекурсивных частей «indexed» и «field» и переместим их на дно.

variable
  ^component, self identifier

component
  ^indexed / field

indexed
  ^variable, subscript

field
  ^variable, fieldName

start
  ^variable


subscript
    ^$[ asParser, #digit asParser, $] asParser

fieldName
    ^$. asParser, self identifier

identifier
  ^(#letter asParser, (#word asParser) star) flatten

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

variable
    ^self identifier, variable'

, теперь variable' на самом деле относится к чему-то с использованным идентификатором, и мы можем безопасно переместить отторжение слева от indexed и field Справа в variable':

variable'
    component', variable' / nil asParser

component'
    ^indexed' / field'

indexed'
    ^subscript

field'
    ^fieldName

Я написал этот ответ, фактически не проверяя код, но должен быть в порядке. Синтаксический анализатор может быть еще более упрощен, я оставляю это как упражнение;).

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

7
задан chills42 3 February 2009 в 13:36
поделиться

10 ответов

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

Тестирование тестов кажется просто способом переместить проблему вместо того, чтобы решить его. Кто собирается протестировать тесты, которые тестируют тесты? 'Прием', что использование TDD для проверки тестов на самом деле полезно, заставляя их перестать работать сначала. Это могло бы быть чем-то, что можно использовать здесь также. Запишите тест, посмотрите, что он перестал работать, затем исправляет код.

11
ответ дан 6 December 2019 в 04:59
поделиться

Я не думаю, что Вы должны модульный тест Ваши модульные тесты.

Но, если Вы записали свою собственную библиотеку тестирования, с пользовательскими утверждениями, контроллерами клавиатуры, тестерами кнопки или что когда-нибудь, затем да. Необходимо записать модульные тесты, чтобы проверить, что они все работают intented.

Библиотека NUnit является единицей, протестированной, например.

9
ответ дан 6 December 2019 в 04:59
поделиться

В теории это - программное обеспечение и таким образом должно быть протестировано на единицу. При прокрутке собственной библиотеки Unit Testing, особенно, Вы захотите к модульному тесту ее, когда Вы идете.

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

5
ответ дан 6 December 2019 в 04:59
поделиться

Вы могли бы хотеть смотреть на то, Кто тестирует тесты.

Короткий ответ - то, что код тестирует тесты, и тесты тестируют код.

Ха?

Тестирование атомных часов
Позвольте мне запуститься с аналогии. Предположим, что Вы путешествуете с атомными часами. Как Вы знали бы, что часы калибруются правильно?

Один путь состоит в том, чтобы спросить Вашего соседа с атомными часами (потому что все несут один вокруг), и сравните два. Если они оба сообщают о том же времени, то у Вас есть высокая степень уверенности, они оба корректны.

Если они отличаются, то Вы знаете один, или другой является неправильным.

Таким образом в этой ситуации, если единственный вопрос Вы спрашиваете, "Мои часы дают корректное время?", затем Вы действительно нуждаются в третьих часах для тестирования вторых часов и четвертых часов для тестирования третьего? Не, если все. Переполнения стека избегают!

IMPO: это - компромисс между тем, сколько времени Вы имеете и сколько качества требуется иметь.

  • Если бы я использовал бы самодельный тест harnas, я протестировал бы его, если время разрешает.
  • Если бы это - сторонний инструмент, я использую, я ожидал бы, что поставщик протестирует его.
5
ответ дан 6 December 2019 в 04:59
поделиться

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

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

2
ответ дан 6 December 2019 в 04:59
поделиться

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

1
ответ дан 6 December 2019 в 04:59
поделиться

Книга Kent Beck "Разработка через тестирование: Примером" имеет пример разработки через тестирование платформы модульного теста, таким образом, конечно, возможно протестировать Ваши тесты.

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

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

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

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

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

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

2
ответ дан 6 December 2019 в 04:59
поделиться

Тесты тестируют код, и код тестирует тесты. Когда Вы говорите, что то же намерение двумя различными способами (однажды в тестах и однажды в коде), вероятность их обоих являющихся неправильным является очень низким (если уже требования не были неправильными). Это может сравниться с двойной бухгалтерией записи, используемой бухгалтерами. См. http://butunclebob.com/ArticleS.UncleBob.TheSensitivityProblem

Недавно была дискуссия об этой той же проблеме в комментариях http://blog.objectmentor.com/articles/2009/01/31/quality-doesnt-matter-that-much-jeff-and-joel


О Вашем вопросе, который должен библиотеки тестирования GUI быть протестированным... Если я понял право, Вы делаете свою собственную библиотеку тестирования, и Вы хотите знать, необходимо ли протестировать библиотеку тестирования. Да. Чтобы смочь полагаться на библиотеку для создания отчетов о тестах правильно у Вас должны быть тесты, которые удостоверяются, что библиотека не сообщает ни о каких ложных положительных сторонах или ложных отрицательных сторонах. Независимо от того, являются ли тесты модульными тестами, интеграционными тестами или приемочными испытаниями, должно быть по крайней мере некоторые тесты.

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

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

2
ответ дан 6 December 2019 в 04:59
поделиться

Обычно мы используем следующие практические правила:

1) Весь код продукта имеет как модульные тесты (организованные так, чтобы они соответствовали классам и функциям кода продукта), так и отдельные функциональные тесты (организованные видимые пользователем функции)

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

3) Модульные и функциональные тесты - нет, сами, когда-либо непосредственно протестированные - APART от использования процедуры TDD для написания теста до кода продукта, а затем запуска теста, чтобы увидеть, как он не работает. Если вы этого не сделаете, вы будете поражены тем, насколько легко случайно написать тесты, которые всегда проходят. В идеале вы должны реализовывать свой код продукта по одному шагу за раз и запускать тесты после каждого изменения, чтобы увидеть, что каждое утверждение в вашем тесте завершается ошибкой, а затем реализуется и начинает проходить. Тогда вы увидите, что следующее утверждение не работает. Таким образом, ваши тесты ДЕЙСТВИТЕЛЬНО проходят тестирование, но только во время написания кода продукта.

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

Это нам очень пригодилось. Кажется, мы всегда придерживались этих правил на 100%, и мы очень довольны нашим соглашением.

В идеале вы должны реализовывать свой код продукта по одному шагу за раз и запускать тесты после каждого изменения, чтобы увидеть, что каждое утверждение в вашем тесте завершается ошибкой, а затем реализуется и начинает проходить. Тогда вы увидите, что следующее утверждение не работает. Таким образом, ваши тесты ДЕЙСТВИТЕЛЬНО проходят тестирование, но только во время написания кода продукта.

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

Это нам очень пригодилось. Кажется, мы всегда придерживались этих правил на 100%, и мы очень довольны нашим соглашением.

В идеале вы должны реализовывать свой код продукта по одному шагу за раз и запускать тесты после каждого изменения, чтобы увидеть, что каждое отдельное утверждение в вашем тесте терпит неудачу, затем будет реализовано и начато прохождение. Тогда вы увидите, что следующее утверждение не работает. Таким образом, ваши тесты ДЕЙСТВИТЕЛЬНО проходят тестирование, но только во время написания кода продукта.

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

Это нам очень пригодилось. Кажется, мы всегда придерживались этих правил на 100%, и мы очень довольны нашим соглашением.

Тогда вы увидите, что следующее утверждение не работает. Таким образом, ваши тесты ДЕЙСТВИТЕЛЬНО проходят тестирование, но только во время написания кода продукта.

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

Это нам очень пригодилось. Кажется, мы всегда придерживались этих правил на 100%, и мы очень довольны нашим соглашением.

Тогда вы увидите, что следующее утверждение не работает. Таким образом, ваши тесты ДЕЙСТВИТЕЛЬНО проходят тестирование, но только во время написания кода продукта.

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

Это нам очень пригодилось. Кажется, мы всегда придерживались этих правил на 100%, и мы очень довольны нашим соглашением.

2
ответ дан 6 December 2019 в 04:59
поделиться

Ответ

Да, ваши библиотеки тестирования графического интерфейса должны быть протестированы.

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

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

Чтобы проверить свой метод CheckGrid :

  • Заполните сетку известными значениями
  • Вызовите метод CheckGrid с заполненными значениями
  • Если этот случай прошел, в хотя бы один аспект CheckGrid работает.
  • Во втором случае вы ожидаете, что метод CheckGrid сообщит об ошибке теста.
  • Подробности того, как вы указываете ожидание, будут зависеть от вашей структуры xUnit (см. Пример ниже). Но в основном, если об ошибке теста не сообщает CheckGrid , то сам тестовый пример должен завершиться ошибкой.
  • Наконец, вам может потребоваться еще несколько тестовых примеров для особых условий, таких как: пустые сетки, несоответствие размера сетки размеру массива.

Вы должны иметь возможность изменить следующий пример dunit для большинства фреймворков, чтобы проверить, что CheckGrid правильно обнаруживает ошибки:

begin
  //Populate TheGrid
  try
    CheckGrid(<incorrect values>, TheGrid);
    LFlagTestFailure := False;
  except
    on E: ETestFailure do
      LFlagTestFailure := True;
  end;
  Check(LFlagTestFailure, 'CheckGrid method did not detect errors in grid content');
end;

Позвольте мне повторить: ваши библиотеки тестирования графического интерфейса должны быть протестированы; и весь фокус в том, как вы это делаете эффективно?

Процесс TDD рекомендует вам сначала выяснить, как вы собираетесь тестировать новую функциональность , прежде чем вы на самом деле ] реализовать ит. Причина в том, что если вы этого не сделаете, вы часто будете ломать голову над тем, как вы собираетесь проверить, что это работает. Переделать тестовые примеры в существующие реализации крайне сложно.

Боковое примечание

Одна вещь, которую вы сказали, меня немного беспокоит ...вы сказали, что на поддержание (ваших тестов) уходит «70% (вашего времени)»

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

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

Некоторые предложения:

  • Остерегайтесь недетерминированных значений. Например, даты и искусственные ключи могут испортить определенные тесты. Вам нужна четкая стратегия решения этой проблемы. (Еще один ответ сам по себе.)
  • Вам нужно будет тесно сотрудничать с «производственными разработчиками», чтобы гарантировать стабилизацию аспектов тестируемых вами интерфейсов. Т.е. Они должны быть осведомлены о том, как ваши тесты идентифицируют компоненты графического интерфейса и взаимодействуют с ними, чтобы они случайно не нарушили ваши тесты изменениями, которые «не влияют на них».
  • По предыдущему пункту, было бы полезно, если бы автоматические тесты запускались всякий раз, когда они вносят изменения.
  • Вам также следует опасаться слишком большого количества тестов, которые просто сводятся к произвольным перестановкам. Например, если у каждого покупателя есть категория A, B, C или D; затем 4 теста «Новый клиент» (по 1 для каждой категории) дают вам 3 дополнительных теста, которые на самом деле не говорят вам намного больше, чем первый, и которые «трудно» поддерживать.
2
ответ дан 6 December 2019 в 04:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: