2012-03-05 128 views
9

我在C#中編寫了Tiger編譯器,我打算將Tiger代碼翻譯爲IL在我的編譯器中編寫單元測試(生成IL)

在對AST中的每個節點執行語義檢查時,我爲此創建了許多單元測試。這是非常簡單的,因爲我的CheckSemantic方法是這樣的:

public override void CheckSemantics(Scope scope, IList<Error> errors) { 
... 
} 

所以,如果我想要寫一些節點的語義檢查一些單元測試,所有我需要做的就是建立一個AST和呼叫該方法。然後,我可以這樣做:

Assert.That(errors.Count == 0); 

Assert.That(errors.Count == 1); 
Assert.That(errors[0] is UnexpectedTypeError); 
Assert.That(scope.ExistsType("some_declared_type")); 

但我開始的代碼生成在這一刻,我不知道編寫單元測試時,這可能是一個很好的做法爲那個階段。

我正在使用ILGenerator類。我想到了以下幾點:

  • 生成我想測試
  • 保存該可執行文件
  • 執行該文件,並輸出存儲在一個文件
  • 反對斷言示例程序的代碼該文件

但我想知道是否有更好的方法呢?

回答

14

這正是我們在C#編譯器團隊上測試我們的IL生成器的過程。

我們還通過ILDASM運行生成的可執行文件並驗證IL是否按預期生成,並通過PEVERIFY運行以確保生成可驗證的代碼。 (當然除了在那些情況下,我們都刻意生成無法驗證的代碼。)

+0

很高興知道這一點。那麼我會這樣做。我只是擔心很多正在運行的測試的性能,以及在磁盤上創建,讀取和刪除文件。 – 2012-03-05 06:16:09

+3

@OscarMederos:如果性能不夠好,那麼要麼(1)分析找出什麼是緩慢的,如果可以的話修復它,或者(2)改變你的測試策略,以便在每次簽入時運行一些測試,一夜之間跑步,有些跑週末。這樣,您就可以快速發現問題並進行徹底的測試。 – 2012-03-05 14:51:02

0

你可以把測試作爲做兩件事情:

  1. 讓你知道,如果輸出已經改變
  2. 讓你知道如果輸出是不正確

確定如果事情已經改變往往大大高於確定的東西是不正確,所以可以比更頻繁地運行變化檢測測試一個很好的策略不正確檢測試驗。

在你的情況下,如果你可以快速確定可執行程序沒有改變,那麼你不需要運行編譯器生成的可執行文件,因爲已經生成了相同可執行文件的已知好的(或假定的)副本。

您通常需要對您正在測試的輸出進行少量操作以消除預期的差異(例如,將嵌入日期設置爲固定值),但一旦完成後,更改檢測測試很容易編寫,因爲驗證基本上是一個文件比較:輸出是否與最後一次已知的良好輸出相同?是:通過,否:失敗。

所以問題是,如果您發現運行由編譯器生成的可執行文件的性能問題,並且檢測到這些程序輸出的更改,則可以選擇通過比較可執行文件本身來運行早期檢測更改的測試。

1

我創建了一個post-compiler in C#,我用這個方法來測試突變CIL:

  1. Save the assemblytemp file,我用它做之後將被刪除。
  2. 使用PEVerifycheck the assembly;如果出現問題,我將其複製到已知位置以進一步進行錯誤分析。
  3. 測試裝配內容。以我爲例,我在一個單獨的AppDomain(所以我以後可以撕裂下來)大多loading the assembly dynamically和行使class in there(因此它就像一個自檢組件:here's a sample implementation)。

我也給出了一些關於如何在this answer中擴展集成測試的想法。