2016-03-08 39 views
2

我想用FSUnit(特別是它的Xunit分支)來測試F#中兩個集合的平等,但迄今爲止發生了可怕的失敗。用FSUnit.Xunit測試集合

我有一個函數返回特定結構的數組,並且想要測試返回的數組是否正確。我正在測試的代碼是在C#中,所以它的功能無法返回本機F#列表。

最有前途的方法我試過是以下幾點:

[<Fact>] 
let SimpleTest() = 
    let parser = new ExpressionParser() 
    parser.ParseExpression "2" |> should equal [new ParsedItem("2", ParsedItemType.Value)] 

...但它導致了測試,因爲失敗:

"Message> FSUnit.Xunit+MatchException: Exception of type 'FsUnit.Xunit+MatchException' was thrown. 

Expected value: Equals [(2)] 
Actual: was [2] 

我可以看到,這是因爲原生F#列表的類型與本地數組不匹配,但不知道(我在文檔中找不到任何東西)如何以不同的方式執行此操作(除非事先創建本地數組並逐個填充它)。

我也嘗試了一些其他的方法,但他們通常甚至不會編譯。 PS:我對F#和Xunit都是全新的,所以我可能會錯過一些絕對明顯的東西。

編輯:,實際工作更好地在評論(比較,而不是對象的字符串表示自己)認爲,雖然我將使用在我實際的代碼,我仍然希望真正解決我的問題上面的一種解決方法。

+0

不是我有一個答案,但可能會幫助其他人看這個。是使用XUnit的一個要求還是你可以改變使用NUnit? –

+0

我可以在沒有任何問題的情況下更改爲NUnit,但更喜歡FSUnit本機解決方案。 – Petrroll

+0

是否有任何理由不能將結構轉換爲可打印格式並比較可打印格式或編寫自定義比較函數並調用該函數。我所從事的一個項目使用了帶有NUnit的FSUnit,並且我們以打印的形式對AST進行了大量比較。請參閱[測試](https://github.com/jack-pappas/fsharp-logic-examples/blob/master/FSharpx.Books.AutomatedReasoning.Tests/equal.fs) –

回答

2

好的,我找到了答案,它比我想象的要簡單。首先我們可以很好地理解這個問題,而且我沒有打算閱讀關於如何在F#中創建數組並僅僅猜測它的文檔。

有兩件事是錯誤的。第一個[new ParsedItem("2", ParsedItemType.Value)]不會創建一個數組,它會創建一個列表。這本身不會成爲FSUnit的should equal的問題,但它足以使用=失敗進行簡單的結構平等測試。

錯了的第二件事是,我並沒有真的[new ParsedItem("2", ParsedItemType.Value)]比較我與[new ParsedItem("2", ParsedItemType.Value), new ParsedItem("+", ParsedItemType.Operator), new ParsedItem("3", ParsedItemType.Value)]比較,實際上創建包含一個touple列表。而且 - 不出所料 - 沒有表現得很好:)。

只需閱讀文檔並瞭解應該創建數組[|new ParsedItem("2", ParsedItemType.Value); new ParsedItem("+", ParsedItemType.Operator); new ParsedItem("3", ParsedItemType.Value)|]修復了此問題。


無論如何,感謝您的意見和其他答案。雖然他們沒有回答我的問題,但他們增加了我對F#的知識,並給了我一個新的想法如何測試:)。

2

儘管無法從C#代碼輕鬆返回F#列表,但有一種選擇是返回數組。這些具有結構相等,所以你可以簡單地比較它們以確定它們是否彼此相等:

open System.Linq 

let csharpArray = Enumerable.Range(0, 10).ToArray() 
let fsharpArray = [| 0..9 |] 

這兩個數組是相等的:

> csharpArray = fsharpArray;; 
val it : bool = true 

如果你不想返回數組,你也可以返回IEnumerable<T>,並轉換爲任意列表或數組中的F#:

> let csharpEnumerable = Enumerable.Range(0, 10);;  
val csharpEnumerable : System.Collections.Generic.IEnumerable<int> 

> csharpEnumerable |> Seq.toList = [0..9];; 
val it : bool = true 

要更全面地介紹使用F#進行單元測試,您可能需要view my Pluralsight course on the topic

+0

那麼測試失敗了呢?我的意思是這些值是相同的,並且ParseExpression返回一個數組?考慮這個問題,它看起來好像「我將結果轉換爲數組不是一個數組,而是一個包含tupple的單元素長陣列(只是根據測試消息猜測)......將研究 – Petrroll

+0

@Petrroll在我的回答中,數組中的* values *是結構相等的int值,因此在F#中所有其他值類型,記錄類型和區別聯合,但大多數.NET對象不會。默認情況下,.NET對象的引用相等。[My Pluralsight course](http://bit.ly/unittestingwithfsharp)有更多詳細信息。 –

+0

是的,我知道,但數組是一個結構數組,結構體有一個默認的EqualityComparer然後(儘管如果結構包含一個ref字段槽慢反射)比較每個成員字段使用他們的相等比較器。而我的stucts成員字段是值類型或字符串(它也有一個覆蓋相等比較器)...所以應該不是問題 – Petrroll