Исходя из примера кода, я не вижу хорошего способа консолидации через наследование. Тесты следуют почти идентичной структуре (создайте экземпляр объекта, сделайте что-нибудь с этим объектом, проверьте результат - ie, Arrange, Act, Assert), но детали реализации существенно отличаются (шаг "act" то же самое, но конструкторы и ожидаемые результаты разные). Платформы тестирования и утверждения уже сделали столько дедупликации, сколько разумно в этом случае.
Примечание: В некоторых платформах модульного тестирования (я в основном использую xUnit. net), можно создать иерархию наследования модульных тестов, в которой все тесты базового устройства выполняются как часть каждого унаследованного устройства, но я не думаю, что это полезно для примера проблемы. Здесь - это другой ответ, описывающий унаследованные тесты.
Если вы открыты для использования xUnit в качестве своей инфраструктуры тестирования, вы можете объединить некоторые тесты с помощью «теорий»:
public class ItemWithNameAndAttributesTests_Theories
{
[Theory]
[InlineData("Name", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" })]
[InlineData("Name", new string[0])]
public void Verify_Constructor_PropertiesAreEqualToInput(string name, string[] attributes)
{
var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, new List<string>(attributes));
Assert.Equal(name, itemWithNameAndAttributes.Name);
Assert.Equal(attributes, itemWithNameAndAttributes.Attributes);
}
[Theory]
[InlineData("", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, typeof(ArgumentException))]
[InlineData(null, new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, typeof(ArgumentNullException))]
[InlineData("Name", null, typeof(ArgumentNullException))]
public void Verify_Constructor_ThrowException(string name, string[] attributes, Type exceptionType)
{
Assert.Throws(exceptionType, () => new ItemWithNameAndAttributes(name, attributes));
}
[Theory]
[InlineData("Name", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, false, "(Item 1) (Item 2) (Item 3) (Item 4) (Item 5)")]
[InlineData("Name", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, true, " (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)")]
[InlineData("Name", new string[0], false, "")]
[InlineData("Name", new string[0], true, "")]
public void Verify_AttributesToParenthesesString(string name, string[] attributes, bool prependSpace, string expected)
{
var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);
var result = itemWithNameAndAttributes.AttributesToParenthesesString(prependSpace);
Assert.Equal(expected, result);
}
[Theory]
[InlineData("Name", new [] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" }, "Name (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)")]
[InlineData("Name", new string[0], "Name")]
public void Verify_ToString(string name, string[] attributes, string expected)
{
var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);
var result = itemWithNameAndAttributes.ToString();
Assert.Equal(expected, result);
}
}
При написании этого примера я заметил, что Verify_AttributesToParenthesesString
несколько избыточен с Verify_ToString
- тестирование ToString
неявно тестирует AttributesToParenthesesString
. Если AttributesToParenthesesString
существует только для поддержки ToString
, то это деталь реализации. Код можно упростить, удалив Verify_AttributesToParenthesesString
и изменив доступ AttributesToParenthesesString
к protected
.