Domanda

tutti. Ho un'interazione sconcertante tra contratti, pex e quickgraph e sarei molto grato per i consigli dei più esperti. L'ho ridotto a un caso di riproduzione in cui commentare un contratto fa sparire il falso negativo, ma non sono stato in grado di diagnosticare con il debugger nel tempo consentito perché il codice soggetto (quickgraph) ha effetti collaterali nella proprietà- getter, il che significa che il debugger esegue gli effetti collaterali durante la visualizzazione dei valori delle proprietà, interferendo con l'effettivo ordine di esecuzione.

Prima un po 'di background, poi le specifiche, poi un puntatore a un progetto da scaricare e provare, se sei così incline a scavare!

Ho installato Pex & Moles

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

e CodeContracts per .NET 4.0

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

Ho scaricato, tramite nuget, la versione più recente di QuickGraph, che è tutto costruito per .NET 3.5. L'ho ridotto al minimo di cui avevo bisogno, sono entrato in Proprietà del progetto per tutti, li ho aggiornati tutti a .NET 4.0 da .NET 3.5 Client Profile, ho corretto una modifica di interruzione della sorgente (che era banale e molto, molto improbabile che avesse una connessione al mio problema). Sono quindi andato alla scheda Contratti codice in ogni pagina del progetto e ho abilitato tutte le opzioni statiche e dinamiche.

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

Il progetto ha 192 unit test, molti dei quali generati da Pex (molto bello!). Per eseguire i test, scarica il file zip del mio progetto da

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

Assicurati di avere Pex & Moles e Contratti dai link sopra. Aprire la soluzione, ricostruire tutto, quindi, a livello di soluzione, "Esegui tutti i test nella soluzione" (control-R, A). Tutto passerà. Quindi vai alla riga 49 di IImplicitUndirectedGraphContracts.cs e rimuovi il commento dal contratto sotto il grande commento (inserito da me). Un test, Prim12240WithDelegate fallirà.

Questo test esercita un costruttore di grafici che costruisce i bordi al volo chiamando un delegato fornito dall'utente nei getter di proprietà per Edges e EdgeCount. Carino. Ma qualcosa va storto con il contratto sulla riga 49 di IImplicitUndirecteGraphContracts.cs.

Questo è un falso negativo, perché se commento questo contratto, il test viene superato. Nel tentativo di seguire questo nel debugger, ha qualcosa a che fare con la tempistica della creazione degli Edges nei getter di proprietà. Non sono stato in grado di districare questo, tuttavia, perché il debugger chiama questi getter, il codice del soggetto li chiama, il codice dei contratti li chiama, forse staticamente, forse dinamicamente, mi sono semplicemente perso cercando di seguirlo, e ho pensato che porterei la domanda a coloro che comprendono i dettagli dell'esecuzione del contratto meglio di me.

Ecco il contratto incriminato; commentarlo fa sì che lo unit test abbia successo:

[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>);
  }
È stato utile?

Soluzione

Pex ha problemi con le espressioni LINQ nel runtime .NET 4.0. dalla prima risposta in questo post del forum MSDN per maggiori dettagli :

Il nostro supporto per Linq funziona per .NET 2.0 / 3.5 ma sembra che abbiamo un file regressione per .NET4.0. Se stai usando 4.0, questo spiegherebbe perché Pex non può generare casi di test interessanti: non strumentalizziamo Linq correttamente.

Perché comunque Pex lotta con Linq: in poche parole, Linq usa DynamicMethod per generare codice. I metodi DynamicMethod non lo sono segnalati al profiler quando vengono jitted. Perché il nostro profiler non può iniettare callback in DynamicMethod, Pex non può tenere traccia del file flusso di dati attraverso la query Linq. Abbiamo una soluzione alternativa che intercetta gli interni del compilatore Linq to Object e lo obbliga a usare Riflessione. Emetti invece.

Ciò avrebbe potuto potenzialmente far sì che ignorasse il contratto che hai commentato durante la sua valutazione, portando al falso negativo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top