Как найти все модульные тесты, которые могут прямо или косвенно вызывать данный метод? (.сеть)

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

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

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

(Мы используем nUnit в .net и у нас много медленных модульных тестов, пройдет много лет, пока мы не рефакторим все наши модульные тесты, чтобы они были быстрыми)

смотрите также:


person Ian Ringrose    schedule 25.03.2011    source источник
comment
Я знаю, что это не инструмент, но когда мне нужно это сделать, я переименовываю метод и пытаюсь скомпилировать, а затем позволяю отладчику сказать мне, что не получается. Однако у меня это работает только в Visual Studio, поэтому полезность ограничена тем, что вы активно отлаживаете, а не на сервере сборки.   -  person David    schedule 25.03.2011
comment
@David, это находит только прямых абонентов.   -  person Ian Ringrose    schedule 25.03.2011
comment
Для меня это похоже на запах. Модульные тесты называются Unit, потому что они тестируют один модуль отдельно от других. Поэтому, как правило, вы должны протестировать класс таким образом, чтобы никакая реализация другого класса не повлияла на тест. Это также означает, что когда вы что-либо меняете в классе, вы должны запускать модульные тесты только для этого класса, потому что другие тесты должны использовать mocks вместо этого класса.   -  person Snowbear    schedule 25.03.2011
comment
@Snowbear, извините, я живу в реальном мире, работая над большой старой кодовой базой в большой команде.   -  person Ian Ringrose    schedule 25.03.2011
comment
Я создал инструмент, который делает это для Python: github.com/jbochi/bazinga   -  person jbochi    schedule 10.07.2011


Ответы (4)


Visual Studio 2010 имеет именно эту функцию: http://blogs.msdn.com/b/phuene/archive/2009/12/07/test-impact-analysis-in-visual-studio-2010.aspx.

Поскольку вы используете nunit, вы также можете попробовать эту технику для запуска MSTest: http://msdn.microsoft.com/en-gb/magazine/cc163643.aspx#S4

person Rob Fonseca-Ensor    schedule 25.03.2011

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

Если ваша реальная цель состоит в том, чтобы иметь возможность быстро проверить, не сломалось ли что-то из-за вашего изменения, я бы порекомендовал:

  • рефакторинг ваших тестов
  • настройка инфраструктуры параллельной сборки с кластером машин сборки (проще, чем вы думаете, с помощью современных инструментов, таких как TeamCity)
person Grzenio    schedule 25.03.2011
comment
Проблема остановки может быть решена во многих полезных реальных случаях, ей просто нужно 3 выхода, да|нет|может быть - тот факт, что мы можем доказать, что нет общего решения, не показывает, что нет решения для многих полезные кейсы. - person Ian Ringrose; 25.03.2011
comment
А в случаях, когда ответ «может быть», вы можете консервативно (в зависимости от ваших потребностей) подтолкнуть его к тому, чтобы рассматривать как «да» или «как если бы нет». Для покрытия тестами, если результат, возможно, этот тест проверяет этот код, вы можете рассматривать это как да, запустить тест снова. - person Ira Baxter; 25.03.2011

Что вам нужно, так это связь между каждым тестом и кодом, который он выполняет.

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

Однако это можно вычислить с помощью инструмента тестового покрытия. Для каждого отдельного теста запустите этот тест (мы предполагаем, что он прошел) и соберите данные о покрытии тестами. Теперь у нас есть много пар (t_i,c_i) для «тест i имеет покрытие c».

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

На самом деле, в идеале вы хотите, чтобы если c_i упоминает какой-либо программный элемент F, и этот программный элемент изменился, вам нужно снова запустить t_i.

Наши инструменты SD Test Coverage предоставляют эту возможность для Java и C# на уровне методов. Вам нужно настроить некоторые сценарии, чтобы связать фактический тест, независимо от того, как вы его упаковали, с собранными векторами тестового покрытия. С практической точки зрения это довольно просто.

person Ira Baxter    schedule 25.03.2011
comment
Спасибо за отличный ответ; Я начал думать в этом направлении. Это то же самое, что делает Visual Studio 2010 с анализом влияния теста? К счастью, у нас не так много кода, управляемого атрибутами (и/или файлами конфигурации), поэтому маловероятно, что изменение метода, который не выполняется тестом, повлияет на результат теста. - person Ian Ringrose; 25.03.2011
comment
@Ian Ringrose: AFAIK, VS 2010 в основном использует инструменты, как и наш инструмент, для сбора этих данных о покрытии. Я не знаю, как они связывают тесты с данными о покрытии тестами, и при этом я не понимаю уровень программного элемента, на котором он дает ответы; это файл? метод? утверждение?. Наши инструменты могут делать это на уровне методов, потому что они фактически анализируют текст и выполняют сравнение. - person Ira Baxter; 25.03.2011

Вы можете использовать «Просмотр иерархии вызовов» VS2010 или ReSharpers «ReSharper -> Проверка -> Входящие вызовы». Вы даже можете экспортировать результат из ReSharper.
Если вы хотите использовать автоматизацию для достижения своей цели, т.е. потому что это не одноразовая вещь, а то, что вы хотите интегрировать в свой процесс сборки, я предлагаю вам построить ваше собственное решение. Вы можете использовать Reflection или Mono.Cecil на сборках и самостоятельно пройти иерархию вызовов. Однако это может занять довольно много времени, поскольку вам потребуется создать полное дерево иерархии вызовов для всех ваших сборок. Другой возможностью было бы создание плагина Visual Studio или ReSharper, чтобы вы могли получить доступ к объектной модели, которую они создают из вашего исходного кода. ваша цель с помощью автоматизации и написания собственного решения будет интересной, но сложной и, возможно, трудоемкой, как при разработке, так и при ее запуске.

person Daniel Hilgarth    schedule 25.03.2011
comment
Справляется ли это с вызовами, которые могут быть сделаны через интерфейсы, делегаты и т. д.? Кроме того, как мне получить его для вывода в формате, который я могу передать в средство запуска модульных тестов? - person Ian Ringrose; 25.03.2011
comment
Хм, я не уверен, что он хорошо справляется с такими случаями. Я только что проверил это на более крупном проекте, и это выглядит странно. В любом случае, вы не можете экспортировать это дерево, поэтому оно может быть вам не очень полезно, если вы хотите использовать какую-то автоматизацию. - person Daniel Hilgarth; 25.03.2011