26

重複の可能性:
コードコントラクトを尊重するようにPexをどのように構成しますか?

現在、pex explorationを実行すると、クラスで作成したコードコントラクトは、pexexplorationの結果でエラーとして扱われます。コードコントラクトを使用してpex探索を実行した場合、コントラクトの失敗は期待される動作として扱われるべきだと思いました。例外の原因となるコードは次のとおりです。

試験方法:

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

メソッド呼び出しの失敗:

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,
               };
}

- - 説明

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

2 に答える 2

0

標準のコントラクトリライターを使用する場合は、失敗時にassertのチェックを外し、型付きのRequires引数を使用してコードをArgumentNullExceptionに変換します。

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

これを行うと、メソッドはargumentnullexceptionsをスローします...pexはそれらと完全にうまく動作します。

コンパイル時に、期待どおりにコントラクトチェックと静的チェックを引き続き実行できます。

PexRaisedContractExceptionが使用方法で動作していないように見えます。ただし、その属性を使用しているとは言えません。あなたの観点からすると、私のやり方は回避策だと思います;)

編集:Pexはこのテストを生成する必要がありますが、テストはエラーをスローする必要があり、それによりテストは合格するはずです。これが機能していないという事実は、リライタが機能していないか、スローされている例外が属性が探している例外タイプではないことを示しています。

于 2011-06-24T15:22:17.300 に答える
0

私の理解では、Pex に関する私の限られた経験から、メソッドはそのContractメソッドに到達するための前提条件を定義するということです。つまり、あなたが言うとき

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

null または空白のユーザー名パラメーターを使用してそのステートメントに到達できる方法はないはずだと言っています。ペックスは基本的にあなたが間違っていると言っています。これは、Pex が本当に得意とすることの 1 つです。これは、メソッドの呼び出しで空/空白の可能性があるNullReferenceExceptionか、空/空白をチェックしていないことを意味します。あなたの仕事は、その場所を見つけることです。メソッドでヌル/空白を処理してからそれを取り除くか、すべての呼び出し元がヌルでも空でもないユーザー名を渡すようにすることで、問題を解決できます。より良い選択は状況によって異なると思いますが、ほとんどの場合、null/空白のユーザー名をusernameCreateUserusernameCreateUserContract.RequiresCreateUserCreateUser方法。そうすれば、コード内の 1 か所でエラーを適切に処理できます。

もちろん、潜在的な問題の中でもユーザー入力の検証の問題を示している可能性があるため、どの呼び出し元が null または空白を渡すことができるかを実際に確認する必要があります。

于 2011-05-18T19:46:00.430 に答える