False Negative Unit Test с Pex, Contracts и QuickGraph

всеки. Имам объркващо взаимодействие между договори, pex и quickgraph и ще бъда много благодарен за съвет от по-осведомените. Сведох го до възпроизвеждащ случай, при който коментирането на един договор кара фалшивия отрицателен резултат да изчезне, но не успях да го диагностицирам с програмата за отстраняване на грешки в разрешеното време, тъй като кодът на темата (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. Намалих го до минимума, от който се нуждаех, влязох в Project Properties за всички, актуализирах ги всички до .NET 4.0 от .NET 3.5 клиентски профил, поправих една промяна, нарушаваща източника (която беше тривиална и много, много малко вероятно да има връзка с моя проблем). След това отидох в раздела Кодови договори на всяка страница на проекта и активирах всички статични и динамични опции.

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

Проектът има 192 модулни теста, много от тях генерирани от Pex (много хубаво!). За да изпълните тестовете, вземете zip файла на моя проект от

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

Уверете се, че имате Pex & Moles и Договори от връзките по-горе. Отворете решението, изградете отново всичко, след това на ниво решение „Изпълнете всички тестове в решение“ (control-R, A). Всичко ще мине. След това отидете на ред 49 от IImplicitUndirectedGraphContracts.cs и разкоментирайте договора под големия коментар (вмъкнат от мен). Един тест, Prim12240WithDelegate, ще се провали.

Този тест упражнява графичен конструктор, който изгражда ръбове в движение чрез извикване на предоставен от потребителя делегат в инструментите за получаване на свойства за Edges и EdgeCount. сладък Но нещо се обърка с договора на ред 49 на IImplicitUndirecteGraphContracts.cs.

Това е фалшиво отрицание, защото ако коментирам този договор, тестът преминава. Опитът да се следва това в програмата за отстраняване на грешки има нещо общо с времето на създаване на ръбовете в инструментите за получаване на свойства. Не успях обаче да разгадая това, тъй като дебъгерът извиква тези гетери, субектният код ги извиква, кодът на договорите ги извиква, може би статично, може би динамично, просто се изгубих, опитвайки се да го следвам, и си помислих, че Бих повдигнал въпроса на тези, които разбират подробностите за изпълнението на договора по-добре от мен.

Ето договора в нарушение; коментирането му прави единичния тест успешен:

[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>);
  }

person Reb.Cabin    schedule 30.01.2011    source източник


Отговори (1)


Pex има проблеми при работа с LINQ изрази в .NET 4.0 runtime. от първия отговор на тази публикация във форума на MSDN за повече подробности:

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

Защо Pex все пак се затруднява с Linq: накратко, Linq използва DynamicMethod за генериране на код. Методите на DynamicMethod не се докладват на профилиращия, когато се изхвърлят. Тъй като нашият профайлър не може да инжектира обратни извиквания в DynamicMethod, Pex не може да проследи потока от данни чрез Linq заявката. Имаме заобиколно решение, което прихваща вътрешността на компилатора Linq to Object и го принуждава да използва Reflection.Emit вместо това.

Това потенциално би могло да го накара да игнорира Договора, който сте коментирали по време на неговата оценка, което да доведе до фалшиво отрицание.

person Ryan Gross    schedule 24.07.2011