Ложный отрицательный юнит-тест с Pex, контрактами и QuickGraph - PullRequest
1 голос
/ 30 января 2011

все. У меня сложное взаимодействие между контрактами, pex и quickgraph, и я был бы очень признателен за советы от более знающих. Я свел это к случаю репро, когда комментирование одного контракта устраняет ложный минус, но я не смог диагностировать его с помощью отладчика за отведенное время, потому что код объекта (быстрый график) имеет побочные эффекты в свойстве getters, что означает, что отладчик выполняет побочные эффекты при отображении значений свойств, влияя на фактический порядок выполнения.

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

Я установил Pex & Moles

http://research.microsoft.com/en-us/projects/pex/downloads.aspx

и CodeContracts для .NET 4.0

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

Я скачал через nuget самую последнюю версию QuickGraph, которая полностью создана для .NET 3.5. Я сократил его до необходимого минимума, зашел в «Свойства проекта» для всех, обновил их до .NET 4.0 из .NET 3.5 Client Profile, исправил одно изменение источника (что было тривиально и очень, очень маловероятно, чтобы я имел какое-либо отношение к моему проблема). Затем я перешел на вкладку «Контракты кода» на каждой странице проекта и включил все статические и динамические параметры.

http://quickgraph.codeplex.com/releases/view/55262

В проекте 192 модульных теста, многие из которых сгенерированы Pex (очень приятно!). Для запуска тестов получите zip-файл моего проекта из

http://dl.dropbox.com/u/1997638/QuickGraph.zip

Убедитесь, что у вас есть Pex & Moles и Contracts по ссылкам выше. Откройте решение, перестройте все, затем на уровне решения «Выполнить все тесты в решении» (control-R, A). Все пройдет. Затем перейдите в строку 49 файла IImplicitUndirectedGraphContracts.cs и раскомментируйте Контракт под большим комментарием (вставленным мной). Один тест, Prim12240WeDelegate не пройдёт.

Этот тест выполняет конструктор графа, который строит ребра на лету, вызывая предоставленный пользователем делегат в свойствах-получателях для Edges и EdgeCount. Милый. Но что-то не так с Контрактом в строке 49 файла IImplicitUndirecteGraphContracts.cs.

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

Вот контракт обидчика; комментирование приводит к успешному выполнению модульного теста:

[Pure]
  IEnumerable<TEdge> IImplicitUndirectedGraph<TVertex, TEdge>.AdjacentEdges(TVertex v)
  {
    IImplicitUndirectedGraph<TVertex, TEdge> ithis = this;
    Contract.Requires(v != null);
    Contract.Requires(ithis.ContainsVertex(v));
    Contract.Ensures(Contract.Result<IEnumerable<TEdge>>() != null);
~~~~~~> Contract.Ensures(
      Enumerable.All(
        Contract.Result<IEnumerable<TEdge>>(),
        edge => 
          edge != null && 
          ithis.ContainsEdge(edge.Source, edge.Target) && 
          (edge.Source.Equals(v) || edge.Target.Equals(v))
        )
      );
    return default(IEnumerable<TEdge>);
  }

1 Ответ

1 голос
/ 25 июля 2011

У Pex есть проблемы, связанные с выражениями LINQ во время выполнения .NET 4.0. из первого ответа на этом сообщении MSDN на форуме для более подробной информации :

Наша поддержка Linq работает для .NET 2.0 / 3.5, но у нас, похоже, есть регрессия для .NET4.0. Если вы используете 4.0, это объясняет, почему Pex не может генерировать интересные тестовые случаи - мы не используем Linq правильно.

Почему Пекс все равно борется с Linq: в двух словах, Linq использует DynamicMethod для генерации кода. Методы DynamicMethod не являются сообщается профилировщику, когда они соединены. Потому что наш профилировщик не может ввести обратные вызовы в DynamicMethod, Pex не может отслеживать поток данных через запрос Linq. У нас есть обходной путь, который перехватывает внутренности компилятора Linq to Object и заставляет его использовать Reflection.Emit вместо этого.

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

...