2011-05-01 30 views
25

可能重複:
How Do You Configure Pex to Respect Code Contracts?Contract.Requires拋出PEX錯誤

目前,當我運行一個PEX的探索,我在班級創建的代碼合同被視爲錯誤pex勘探結果。我認爲,當你使用代碼合同進行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); 
} 
+0

PEX團隊是否會監督這個論壇?還是沒有更多的PEX團隊? – 2011-05-05 01:39:15

+1

我不會稱之爲「pex論壇」,即使來自「他們」的人可能會在此處查看。看起來像[這](http://social.msdn.microsoft.com/Forums/en-US/pex/threads/)是論壇。 – 2011-05-09 12:33:20

+1

我不認爲他們在那裏迴應。在pex主頁上,他們記下論壇已被移至stackoverflow。 [PEX主頁](http://research.microsoft.com/en-us/projects/pex/) – 2011-05-10 01:26:02

回答

0

我的理解,我與Pex的經驗有限,就是Contract方法定義了達到他們所處方法的先決條件。所以,當你說

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

你是說應該沒有辦法用空白或空白的用戶名參數來達到這個聲明。佩克斯基本上是說你錯了。這是Pex的一件事真的有益。這意味着您有可能獲得NullReferenceException或者在您撥打CreateUser方法時未檢查空白/空白username。那麼你的任務就是找到哪裏。您可以通過處理CreateUser方法中的空白/空白username,然後刪除Contract.Requires或通過確保CreateUser的所有呼叫者傳遞非空非空用戶名來解決問題。我認爲更好的選擇取決於你的情況,但在幾乎所有情況下,我都會在CreateUser方法中處理空白/空白用戶名。這樣,您可以在代碼中的一個地方優雅地處理錯誤。

當然,你真的應該看到哪個調用者可以傳遞null或空白,因爲這可能表示用戶輸入驗證問題以及其他潛在問題。

+0

代碼合同正確。但是,當您使用PEX執行參數化單元測試時,應該將代碼合同視爲預期的行爲。所以,即使合同會在運行時拋出一個異常,pex會按預期處理這個異常。 pex單元測試就是這種情況。我認爲這可能是勘探結果的一個缺陷。 – 2011-05-19 17:27:47

+0

@Joshua Dale參見http://research.microsoft.com/en-us/projects/pex/pexandcontracts.pdf的第10-11頁。 「執行運行時合同檢查」的設置是什麼? – Andrew 2011-05-19 17:59:06

+0

爲目標項目打開合同(我也爲測試項目啓用了合約)。此外,我正在獲得一個ContractException,因此代碼合同已啓用。 – 2011-05-20 01:17:02

0

我發現如果您使用標準合約重寫器,請在發生故障時不要觸發assert,並讓您的代碼通過使用類型化的Requires參數來觸發ArgumentNullException。

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

當你這樣做的時候,這些方法會拋出argumentnullexceptions ... pex的表現與他們完全吻合。

在編譯時您仍然可以像您期望的那樣獲得合同檢查和靜態檢查。

它看起來像PexRaisedContractException不與您如何使用它的行爲。我不能說我使用該屬性。我想從你的角度來看,我的方式是一個工作;)

編輯:Pex應該產生這個測試,但測試應該拋出錯誤,並應該導致測試通過。這不起作用的事實表明,重寫器無法正常工作,或者拋出的異常不屬於屬性查找的異常類型。

+0

當使用代碼合同和pex時,pex使用合同失敗作爲預期的異常,並在探索中將其標記爲綠色。您的修復程序確實有效,但您同時使用pex和代碼合同並不會帶來任何好處。 – 2011-07-02 07:12:11

+0

'使用Pex和Contracts'是垃圾,您從中受益無益。按照我所做的方式使用這兩種技術是我的代碼質量的最大進步。對於無法工作的人來說,這是一個相當教條的陳述。即使你確實意味着額外的好處,我仍然不同意,因爲合同給我編譯時間檢查,pex爲我提供了一個探索性測試的好工具。我厭倦了爲空值編寫測試.... – 2011-07-04 12:42:28

+0

對不起。我不是故意淡化你的修復,這很好。我只是簡單地說它並不像它用來做的那樣。獲得支持比使用Pex團隊更成問題。 – 2011-07-04 14:20:08