База модульного тестирования и производный класс - PullRequest
0 голосов
/ 08 февраля 2020

Итак, у меня есть 2 класса. ItemWithAttributes и ItemWithNameAndAttributes. Я немного прочел соглашение о присвоении имен для метода тестирования, но теперь чувствую себя застрявшим.

using System;
using System.Collections.Generic;
using System.Linq;
using Objects.Base;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTests.Objects.Base
{
    [TestClass]
    public class ItemWithAttributesTests
    {
        [TestMethod]
        public void Constructor_AttributesWithElements_PropertyEqualToInput()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            CollectionAssert.AreEqual(attributes, itemWithAttributes.Attributes.ToList());
        }

        [TestMethod]
        public void Constructor_AttributesWithoutElements_PropertyEqualToInput()
        {
            var attributes = new List<string>() { };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            CollectionAssert.AreEqual(attributes, itemWithAttributes.Attributes.ToList());
        }

        [TestMethod]
        public void Constructor_AttributesNull_ThrowArgumentNullException()
        {
            Assert.ThrowsException<ArgumentNullException>(() => new ItemWithAttributes(null));
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithElementsAndPrependFalse_ReturnsEqualString()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.AttributesToParenthesesString(false);

            Assert.AreEqual("(Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithElementsAndPrependTrue_ReturnsEqualString()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.AttributesToParenthesesString(true);

            Assert.AreEqual(" (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithoutElementsAndPrependFalse_ReturnsEqualString()
        {
            var attributes = new List<string>() {  };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.AttributesToParenthesesString(false);

            Assert.AreEqual("", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithoutElementsAndPrependTrue_ReturnsEqualString()
        {
            var attributes = new List<string>() {  };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.AttributesToParenthesesString(true);

            Assert.AreEqual("", result);
        }

        [TestMethod]
        public void ToString_AttributesWithElements_ReturnsEqualString()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.ToString();

            Assert.AreEqual("(Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void ToString_AttributesWithoutElements_ReturnsEqualString()
        {
            var attributes = new List<string>() { };
            var itemWithAttributes = new ItemWithAttributes(attributes);

            var result = itemWithAttributes.ToString();

            Assert.AreEqual("", result);
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using Objects.Base;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTests.Objects.Base
{
    [TestClass]
    public class ItemWithNameAndAttributesTests
    {
        [TestMethod]
        public void Constructor_NameAndAttributesWithElements_PropertiesAreEqualToInput()
        {
            var name = "Name";
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            Assert.AreEqual(name, itemWithNameAndAttributes.Name);
            CollectionAssert.AreEqual(attributes, itemWithNameAndAttributes.Attributes.ToList());
        }

        [TestMethod]
        public void Constructor_NameAndAttributesWithoutElements_PropertiesAreEqualToInput()
        {
            var name = "Name";
            var attributes = new List<string>() { };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            Assert.AreEqual(name, itemWithNameAndAttributes.Name);
            CollectionAssert.AreEqual(attributes, itemWithNameAndAttributes.Attributes.ToList());
        }


        [TestMethod]
        public void Constructor_NameEmpty_ThrowArgumentException()
        {
            var name = string.Empty;
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            Assert.ThrowsException<ArgumentException>(() => new ItemWithNameAndAttributes(name, attributes));
        }

        [TestMethod]
        public void Constructor_NameNull_ThrowArgumentNullException()
        {
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            Assert.ThrowsException<ArgumentNullException>(() => new ItemWithNameAndAttributes(null, attributes));
        }

        [TestMethod]
        public void Constructor_AttributesNull_ThrowArgumentNullException()
        {
            var name = "Name";
            Assert.ThrowsException<ArgumentNullException>(() => new ItemWithNameAndAttributes(name, null));
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithElementsAndPrependFalse_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.AttributesToParenthesesString(false);

            Assert.AreEqual("(Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithElementsAndPrependTrue_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.AttributesToParenthesesString(true);

            Assert.AreEqual(" (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithoutElementsAndPrependFalse_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.AttributesToParenthesesString(false);

            Assert.AreEqual("", result);
        }

        [TestMethod]
        public void AttributesToParenthesesString_AttributesWithoutElementsAndPrependTrue_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.AttributesToParenthesesString(true);

            Assert.AreEqual("", result);
        }

        [TestMethod]
        public void ToString_AttributesArgumentIsListWithElements_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.ToString();

            Assert.AreEqual("Name (Item 1) (Item 2) (Item 3) (Item 4) (Item 5)", result);
        }

        [TestMethod]
        public void ToString_AttributesArgumentIsListWithoutElements_ReturnsEqualString()
        {
            var name = "Name";
            var attributes = new List<string>() { };
            var itemWithNameAndAttributes = new ItemWithNameAndAttributes(name, attributes);

            var result = itemWithNameAndAttributes.ToString();

            Assert.AreEqual("Name", result);
        }
    }
}

Что я заметил, так это то, что модульные тесты для моего производного класса ItemWithNameAndAttributes почти одинаковы что касается моего базового класса ItemWithAttributes, но немного больше и отличается, потому что мне также нужно проверить для аргумента имени. Я не уверен, что это правильный путь к go или есть какой-то метод для повторного использования тестов из моего базового класса в моем производном классе. Если я продолжу этот текущий шаблон, когда я получу из ItemWithNameAndAttributes, у меня будет еще больше тестов, которые будут одинаковыми, и проведу повторное тестирование базовых классов. У меня было ощущение, что это очень сложно очень быстро для маленьких классов, которые у меня есть.

1 Ответ

0 голосов
/ 08 февраля 2020

Исходя из примера кода, я не вижу хорошего способа консолидации через наследование. Тесты следуют почти идентичной структуре (создайте экземпляр объекта, сделайте что-нибудь с этим объектом, проверьте результат - 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...