2011-05-01 9 views
25

Duplicar posibles:
How Do You Configure Pex to Respect Code Contracts?Contract.Requires lanzan errores pex

En la actualidad, cuando ejecuto una exploración PEX, los contratos de código que he creado en mis clases están siendo tratados como errores en los resultados de exploración pex. Cuando se ejecutó la exploración pex utilizando contratos de código, pensé que las fallas de contrato deberían tratarse como un comportamiento esperado. Aquí está el código que causa las excepciones.

Método de prueba:

[PexMethod] 
public void TestEquality(Guid userId, string username, string password, string securityQuestion, string securityAnswer) 
{ 
    UserSecurity user = UserTools.CreateUser(Guid.NewGuid(), username, password, securityQuestion, securityAnswer); 

    bool passwordResult = UserTools.VerifyInput(password, user.Password, user.PasswordSalt); 
    bool securityAnswerResult = UserTools.VerifyInput(securityAnswer, user.SecurityAnswer, user.SecurityAnswerSalt); 

    Assert.IsTrue(passwordResult, "Password did not correctly re-hash"); 
    Assert.IsTrue(securityAnswerResult, "Security Answer did not correctly re-hash"); 
} 

método A falta de llamada:

public static UserSecurity CreateUser(Guid userId, string username, string password, string securityQuestion, string securityAnswer) 
{ 
    Contract.Requires(userId != Guid.Empty); 
    Contract.Requires(!string.IsNullOrWhiteSpace(username)); 
    Contract.Requires(!string.IsNullOrWhiteSpace(password)); 
    Contract.Requires(!string.IsNullOrWhiteSpace(securityQuestion)); 
    Contract.Requires(!string.IsNullOrWhiteSpace(securityAnswer)); 
    Contract.Ensures(Contract.Result<UserSecurity>() != null); 

    byte[] passwordSalt; 
    byte[] securityAnswerSalt; 

    return new UserSecurity 
       { 
        UserId = userId, 
        Username = username, 
        Password = SecurityUtilities.GenerateHash(password, out passwordSalt), 
        PasswordSalt = passwordSalt, 
        SecurityQuestion = securityQuestion, 
        SecurityAnswer = SecurityUtilities.GenerateHash(securityAnswer, out securityAnswerSalt), 
        SecurityAnswerSalt = securityAnswerSalt, 
       }; 
} 

--- Descripción

failing test: ContractException, Precondition failed: !string.IsNullOrWhiteSpace(username) 

Guid s0 
    = new Guid(default(int), (short)32, (short)32, default(byte), default(byte), 
       default(byte), default(byte), default(byte), 
       default(byte), default(byte), default(byte)); 
this.TestEquality(s0, (string)null, (string)null, (string)null, (string)null); 


[TestMethod] 
[PexGeneratedBy(typeof(HashTests))] 
[PexRaisedContractException] 
public void TestEqualityThrowsContractException173() 
{ 
    Guid s0 
     = new Guid(default(int), (short)32, (short)32, default(byte), default(byte), 
        default(byte), default(byte), default(byte), 
        default(byte), default(byte), default(byte)); 
    this.TestEquality(s0, (string)null, (string)null, (string)null, (string)null); 
} 
+0

¿El equipo PEX incluso monitorea este foro? ¿O no hay más equipo de PEX? –

+1

No llamaría a esto el "foro pex", aunque alguien de "ellos" podría consultar aquí. Parece que [este] (http://social.msdn.microsoft.com/Forums/en-US/pex/threads/) es el foro. –

+1

No creo que respondan allí nunca más. En la página de inicio de pex, anotan que los foros se han movido a stackoverflow. [página de inicio de Pex] (http://research.microsoft.com/en-us/projects/pex/) –

Respuesta

0

Mi comprensión, desde mi experiencia limitada con Pex, es que el Contract Los métodos definen las condiciones previas para llegar al método en el que se encuentran. Por lo tanto, cuando diga

Contract.Requires(!string.IsNullOrWhiteSpace(username)); 

está diciendo que no debería haber forma de que se pueda llegar a esa declaración con un parámetro de nombre de usuario nulo o blanco. Pex básicamente dice que estás equivocado. Esto es una cosa, Pex es realmente bueno para. Significa que tiene el potencial para NullReferenceException o que no está buscando un espacio vacío/en blanco username en alguna llamada a su método CreateUser. Su tarea, entonces, es encontrar dónde. Puede solucionar el problema manejando null/whitespace username en el método CreateUser, luego deshacendolo del Contract.Requires, o asegurándose de que todas las personas que llaman de CreateUser pasen un nombre de usuario no nulo y no vacío. La mejor opción depende de su situación, creo, pero en casi todos los casos, manejaría el nombre de usuario null/whitespace en el método CreateUser. De esta forma, puedes manejar el error correctamente en un lugar en tu código.

Por supuesto, realmente debería ver qué llamante puede pasar nulo o en blanco, ya que esto podría indicar un problema de validación de entrada del usuario, entre otros problemas potenciales.

+0

Eso es correcto para los contratos de código. Sin embargo, cuando utiliza PEX para realizar pruebas unitarias parametrizadas, debe tratar los contratos de código como comportamiento esperado. Entonces, aunque el contrato lanzaría una excepción en el tiempo de ejecución, pex trata esta excepción como se esperaba. Este es el caso para las pruebas de unidad pex. Creo que esto puede ser un error con los resultados de exploración. –

+0

@Joshua Dale Consulte las páginas 10-11 de http://research.microsoft.com/en-us/projects/pex/pexandcontracts.pdf. ¿Cuál es su configuración para "Realizar la verificación del contrato en tiempo de ejecución"? – Andrew

+0

Los contratos están activados para el proyecto de destino (también lo habilité para el proyecto de prueba solo para estar seguro). También recibo una ContractException actualmente, por lo que los contratos de código están habilitados. –

0

Me parece que si utiliza el reescritor de contrato estándar, desactive la afirmación en caso de error y deje su código en ArgumentNullException utilizando un argumento de tipo Requiere.

contract.Requires<ArgumentNullException>(i!=null); 

cuando haces esto, los métodos lanzarán argumentnullexceptions ... pex se comporta muy bien con ellos.

En tiempo de compilación aún obtiene la verificación de contrato y la comprobación estática como era de esperar.

Parece que PexRaisedContractException no se comporta como lo usa. Sin embargo, no puedo decir que use ese atributo. Supongo que desde su punto de vista mi camino es un trabajo;)

EDITAR: Pex debe generar esta prueba, pero la prueba debe arrojar el error y eso debe hacer que la prueba pase. el hecho de que esto no funcione me sugiere que la reescritura no funciona o que la excepción que se lanza no es el tipo de excepción que busca el atributo.

+0

Al usar contratos de código y pex, pex usa las fallas contractuales como excepciones esperadas y las marca verdes en las exploraciones. Tu solución funciona, pero no obtienes ningún beneficio al usar contratos de Pex y código juntos. –

+0

'No obtiene ningún beneficio del uso de Pex y Contracts' que es basura. Usar estas 2 tecnologías en la forma en que lo estoy haciendo ha sido el mayor avance en la calidad de mi código para mí. Para alguien que no puede hacer que funcione es una declaración bastante dogmática. Incluso si significó un beneficio adicional, todavía estoy en desacuerdo porque los contratos me dan un tiempo de compilación y pex me da una gran herramienta para las pruebas exploratorias. Me aburro de escribir pruebas para valores nulos ... –

+0

Lo siento. No quise minimizar tu solución, que funciona bien. Simplemente estaba diciendo que no se está comportando como solía hacerlo. Y obtener soporte ha sido más problemático de lo que solía hacerlo con el equipo de pex. –

Cuestiones relacionadas