Существует ли путь к модульному тесту против побочных эффектов?

Любой код может обеспечить побочные эффекты. Большую часть времени побочные эффекты могут быть знаком плохого дизайна и/или потребностью перефакторизации, но когда поблочное тестирование мне трудно протестировать против. Рассмотрите следующий пример:

[Test]
public void TrimAll_Removes_All_Spaces()
{
    // Arrange
    var testSubject = "A    string  with     lots   of     space";
    var expectedResult = "Astringwithlotsofspace";

    // Act
    var result = testSubject.TrimAll();

    // Assert
    Assert.AreEqual(expectedResult, result);
}

это тестирует следующее расширение:

public static string TrimAll(this string str)
{
    PokeAround();

    return str.Replace(" ", "");
}

Тест передаст, но нет никакой защиты agains побочных эффектов. Эффекты вызова к PokeAround пойдет абсолютно незамеченный.

Учитывая, что Вы не знаете что PokeAround - это могло быть что-либо! - как Вы пишете тест, который принимает меры против него? Это вообще возможно?

Разъяснение: было несколько комментариев о PokeAround как абсолютно неизвестный являющийся очень маловероятным сценарием, так как у нас есть источник, когда мы пишем тест. Причина, которую я задал этому вопросу, тем не менее, состояла в том, чтобы найти способ принять меры против побочных эффектов, добавленных позже. Таким образом, когда я пишу тест, у меня мог бы быть exension метод, похожи на это:

public static string TrimAll(this string str)
{
    return str.Replace(" ", "");
}

Тестовые передачи, все хорошо. Затем месяц спустя, когда я на каникулах, add's коллеги PokeAround звонить. Я хочу тест, который я уже записал для сбоя, потому что он сделал.

11
задан Tomas Aschan 30 July 2010 в 12:49
поделиться

8 ответов

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

Учитывая, что вы не знаете, что такое PokeAround - это может быть что угодно!

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

Обновление: , чтобы быть уверенным, что будущие изменения в методе модульного тестирования никогда не будут иметь каких-либо непредвиденных побочных эффектов? Я думаю, вы

  1. не можете,
  2. не должны.

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

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

12
ответ дан 3 December 2019 в 05:56
поделиться

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

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

Инструменты тестирования BDD / Integration также помогут в этом, поскольку они (обычно) тестируют более широкие области функциональности, а не только отдельные классы / методы.

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

0
ответ дан 3 December 2019 в 05:56
поделиться

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

Без полного регрессионного теста невозможно обнаружить побочные эффекты.

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

Надеюсь, это поможет.

0
ответ дан 3 December 2019 в 05:56
поделиться

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

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

Также может помочь такой инструмент, как Jester , но я не думаю, что это будет иметь значение в вашем примере.

0
ответ дан 3 December 2019 в 05:56
поделиться

У меня нет личного опыта, но это может вас заинтересовать: Контракты кода

http://research.microsoft.com/en-us/projects/contracts/

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

2
ответ дан 3 December 2019 в 05:56
поделиться

Учитывая, что вы не знаете, что такое PokeAround - это может быть что угодно! - как написать тест, который защитит от этого? Возможно ли это вообще?

Этот вопрос нелепый. В реальном мире такая ситуация маловероятна.

  1. Вы всегда знаете, что такое PokeAround. Это модульное тестирование. У вас есть исходники.

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

    Если вы не знаете, что такое PokeAround, у вас есть люди, которые специально злобствуют и препятствуют успеху. Им нужна новая работа. Или вам нужно.

  2. Вы должны использовать Mocks для этого PokeAround, чтобы вы могли наблюдать побочные эффекты.

"защититься от побочных эффектов, добавленных позже".

Это не пример загадочного куска кода. Вы все равно знаете, что такое PokeAround. Вы всегда знаете, что такое PokeAround.

Вот почему мы проводим регрессионное тестирование. http://en.wikipedia.org/wiki/Regression_testing

Это все еще модульное тестирование.

  • Вы все еще тестируете PokeAround отдельным модульным тестом.

  • И вы тестируете вещи, которые используют PokeAround, с помощью макета PokeAround.

2
ответ дан 3 December 2019 в 05:56
поделиться

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

0
ответ дан 3 December 2019 в 05:56
поделиться

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

Google Test (для C ++) может сделать это ; Я не знаю других фреймворков, в которых есть эта функция.

0
ответ дан 3 December 2019 в 05:56
поделиться
Другие вопросы по тегам:

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