2009-12-21 86 views
1

我已經檢查了這個.. similar question但我不確定答案...有沒有辦法爲接口編寫測試,然後對所有實現測試的類進行測試?

我目前有一個接口只能由一個類實現,但是遲早會發生變化。我現在有對接口的測試,並在一開始所有測試開始:

IFoo foo = GetConcreteFoo() 

其中GetConcreteFoo是一樣的東西

IFoo GetConcreteFoo() 
{ 
    return new ConcreteFooA(); 
} 
然而

,當我拿到美孚的多種實現,莫不是一種使所有測試運行在所有不同具體foos列表上的方法?

我認爲,如果沒有辦法,至少我可以複製/粘貼測試到一個新的文件,具體類的名稱,並更改GetConcreteFoo的返回對象...並且更改原始文件從(IFooTests到IConcreteFooATests)。

我不認爲這種方法是特別壞..但它不是太優雅/高明,因爲這將是在其上運行的所有具體實現相同的測試(文件)。

有沒有辦法讓它做到這一點?

(Im使用MSTests)

謝謝!

回答

3

不確定MSTest,但我相信你可以在NUnit中使用parameterised tests(例如,用實現類參數化並使用Activator.CreateInstance來實例化它。

但是,更深層的問題是,你想嗎?你沒有說你的界面是什麼樣的,但是有一個界面的通常原因是允許不同的實現。例如,如果您有一個具有Area屬性的IShape接口,那麼Circle,Square和RorschachBlot將以不同方式實現。 IShape.Area屬性的測試能夠可靠地聲明什麼?因此,一般來說,您可以真實地測試類和(具體)方法。當然,如果你的界面是爲了暗示界面規範之外的語義保證(例如Area總是大於0),那麼你可以測試你知道的所有實現。 (對於您在創建測試時不知道的實現,您必須依靠通過文檔傳遞這些額外的需求,並相信實現者遵守這些要求。當代碼合同發佈後,您將能夠實施這些要求通過合同類更可靠。)

+0

+1總體而言,這是一個很好的答案,但做這樣的集成測試也可以作爲迴歸測試套件。另一件事是,如果你有一個接口暗示「接口規範之外的語義保證」,那麼它就是抽象類而不是接口的主要候選者。 –

+0

是的界面確實意味着語義上的保證,因爲它是一個獨立於實現的存儲庫,getAll全部獲取,Add添加一個新元素,Update更新一個元素等。該方法應該始終具有相同的可測試結果,獨立於實施。 我應該讓它成爲一個抽象類嗎?如果我這樣做,我仍然需要測試所有的實現。 雖然談論參數化測試讓我思考PEX,但我也要檢查一下。 –

2

簡短的回答,是的,你可以。較長的回答是,它將取決於很多因素,如何在你的測試套件。

基本上你可以做這樣的事情:

public void GenericIFooTest(IFoo testFoo) { 
    // each of your tests against foo here... 
    Assert.IsTrue(testFoo.DoesItsThing()); 
} 

然後,您可以手動生成測試:

public void TestConcreteAFoo() { 
    IFoo aFoo = new ConcreteAFoo(param1, param2, param3); 

    GenericIFooTest(aFoo); 
} 
public void TestConcreteBFoo() { 
    IFoo bFoo = new ConcreteBFoo(); 

    GenericIFooTest(bFoo); 
} 

或者你可以使用反射來做到這一點。這是假設你知道如何動態實例每個富,如果它有一個默認的構造函數,這將是最好的:

public void TestAllFoos() { 
    foreach(string assembly in Directory.GetFiles(assemblyPath, "*.dll", SearchOptions.All) { 
     Assembly currentAssembly = Assembly.LoadAssembly(assembly); 

     foreach(Type internalTypes in currentAssembly.GetTypes()) { 
     if (internalTypes.IsAssignableFrom(IFoo) && !(internalTypes is IFoo)) { 
      IFoo fooType = AppActivator.CreateInstance(internalTypes); 

      GenericIFooTest(fooType); 
     } 
     } 
    } 
} 

最後一部分是從一些代碼的存儲器我上週寫做同樣的事情,它的有點粗糙,但應該讓你開始。你當然可以使用LINQ來簡化它,我只是不知道我頭頂的語法。

+0

你的建議是相當不錯的選擇,我會嘗試他們和參數化的測試,看看我覺得最舒服:) –

+0

你可以將它們與參數化測試結合起來,也許使用參數來加載你所關心的組件或類型。 – GrayWizardx

相關問題