簡體   English   中英

兒童班的單元測試

[英]Unit testing of child classes

假設我們有這個超級簡單的類hierchy:

public class SomeMath
{
    public int Add(int x, int y)
    {
        return x + y;
    }
}

public class MoreMath : SomeMath
{
    public int Subtract(int x, int y)
    {
        return x - y;
    }
}

在為MoreMath類編寫測試時,我應該為Add方法編寫測試嗎? 或者我在測試SomeMath類時是否應該只關心該方法? 更一般地說:我應該測試一個類的所有方法,還是應該只測試“新”方法?

我可以想出雙方的一些理由。 例如,在測試所有方法時,您最終會不止一次地測試相同的東西,這不是很好,而且可能變得乏味。 但是如果你不測試所有方法, SomeMath的更改可能會破壞MoreMath用法? 這也是一件壞事。 我想這也可能取決於案例。 就像它擴展了一個類,我可以控制或不控制。 但無論如何,我是一個全新的測試新手,所以我很想知道人們比我想的更聰明:-)

通常我不會測試子類中的行為,除非子類改變了父類中預期的行為。 如果它使用相同的行為,則無需進行測試。 如果您計划對父類進行重大更改但子類仍然需要舊行為,那么我將首先在子類中創建測試以定義其所需行為,然后我將在父測試中進行更改代碼更改。 這遵循YAGNI原則 - 您不需要它 - 並延遲子測試的實施,直到它們實際有目的。

我只測試SomeMath類的Add方法。 如果MoreMath只繼承它並且絕對沒有什么新東西,那么為兩者編寫測試將是純粹的重復代碼,僅此而已。 用這些東西做一點務實總是好的。

在我目前的地方,我們遇到了一個類似的問題,我們希望開發接口,但要確保接口的每個實現都能正常運行(例如,不管該層的實現如何,不同的數據層應該表現相同)。 我們解決它的方式(使用NUnit)是在單元測試中有一個繼承結構:

public interface ICalculator
{
  public int Add(int a, int b)
}

public class Calculator : ICalculator
{
  public int Add(int a, int b) { return a + b; }
}

public class TestCalculatorInterface
{
   public abstract SomeMath GetObjectToTest();

   [Test]
   public void TestAdd()
   {
       var someMath = GetObjectToTest();
       ...
   }
}    

[TestFixture]
public class TestCalculator: TestCalculatorInterface
{
   public virtual Calculator GetObjectToTest() { return new Calculator(); }
}

我們在基本接口測試中沒有[TestFixture]屬性,但在所有測試方法上都有[Test]屬性。 TestCalculator類是[TestFixture],但是繼承了基類的所有測試,這使得子類只負責提供測試該接口的對象。

我會為你的情況采用類似的模式,所以測試是針對所有類運行的,但只寫一次。

首先,我認為至少有兩個因素可能會影響您做出其中一個的決定:

  • 繼承的目的是什么?
  • 有問題的測試的目的是什么?

在TDD場景中,我傾向於為MoreMath編寫一個測試用例來驗證它是從SomeMath派生的,然后考慮從SomeMath繼承的所有成員都被覆蓋。

但是,這意味着,從設計角度來看,MoreMath派生自SomeMath是一個重要的設計方面。 如果您以多態方式使用SomeMath,肯定會出現這種情況。 但是,如果您只是使用繼承來重用(不推薦),則情況並非如此。

在后一種情況下(繼承用於重用),父類和子類之間沒有概念連接,並且您可能想要在將來中斷繼承。 在這種情況下,進行測試以驗證父母是否正確是一個很差的保障措施。

從質量保證(QA)的角度來看,每個班級的每個成員都應該經過嚴格的測試。 這意味着即使測試代碼相同,您也應該為每個子類重復測試代碼,因為您需要驗證沒有以意外方式覆蓋虛擬方法。 但是,要保持DRY,您可以將它們編寫為參數化測試,或者使用Pex等工具。

就個人而言,我很少進入質量保證階段。 通常,在TDD期間創建的測試套件是一個足夠的安全網......但這一切都取決於您構建的軟件類型。

我會讓我的測試類MoreMath從測試類繼承SomeMath ,從而繼承所有類的測試。 這意味着我只需要為新功能編寫額外的測試,但所有子類的功能都經過了全面測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM