Testy jednostkowe - podejście i dokładność

0

Cześć,
Mam taki problem, gdyż staram się wyrobić nawyk pisania testów jednostkowych (TDD) i czytając różne kursy i poradniki spotkałem się z wieloma podejściami do testów.
Najbardziej przekuje mnie podejście że test powinien być prosty i szybki, niezależny i niekonfigurowalny.
Teraz mam do was pytanie które z poniższych podejść jest lepsze, a może obydwa są złe? Oraz drugie pytanie jak dokładnie testować aplikacje?

Przykładowy kod C# & nUnit

 using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    [TestFixture]
    public class CalculatorUnitTest
    {

        //[SetUp]
        //public void Initialize()
        //{
        //    ICalculator calculator = new Calculator();
        //}

        [Test, Combinatorial]
        public void Add_TNumbers_Calculated([Values(-2, -2.2, 0, 2, 2.2)]double first, [Values(-3, -3.3, 0, 3, 3.3)]double second)
        {
            // Arrange:
            ICalculator calculator = new Calculator();
            double expected = first + second;

            // Act:
            double result = calculator.Add(first, second);

            // Assert:
            Assert.AreEqual(expected, result);
        }



        [TestCase(2, 2, 4)]
        [TestCase(-2, -2, -4)]
        [TestCase(2, -2, 0)]
        [TestCase(-2, 2, 0)]
        [TestCase(-2, 0, -2)]
        [TestCase(2, 0, 2)]
        [TestCase(0, -2, -2)]
        [TestCase(0, 2, 2)]
        [TestCase(0, 0, 0)]
        [TestCase(3, 2, 1)]
        [TestCase(-3, -2, -5)]
        [TestCase(3, 0, 3)]
        [TestCase(-3, 0, -3)]
        [TestCase(0, 2, -2)]
        [TestCase(0, -2, -2)]
        [TestCase(-3, 2, -1)]
        [TestCase(3, -2, 5)]
        [TestCase(0, 0, 0)]
        [TestCase(3.3, 2, 1.3)]
        [TestCase(3.3, 2.2, 1.1)]
        [TestCase(-3.3, -2.2, -1.1)]
        [TestCase(3.3, 0, 3.3)]
        [TestCase(-3.3, 0, -3.3)]
        [TestCase(0, 2.2, -2.2)]
        [TestCase(0, -2.2, -2.2)]
        [TestCase(-3.3, 2.2, -5.5)]
        [TestCase(3.3, -2.2, 5.5)]
        public void Add_TwoNumbers_Calculated_SecontMethod(double first, double second, double expected)
        {
            // Arrange:
            ICalculator calculator = new Calculator();

            // Act:
            double result = calculator.Add(first, second);

            // Assert:
            Assert.AreEqual(expected, result);
        }

    }
}
1

Pierwsze rozwiązanie ma jedna dużą wadę: musisz dokonać obliczeń wartości oczekiwanej i tu pojawia się ryzyko.
Twój przykład jest prosty i wygląda jakby nie było problemu, ale w bardziej realnych przypadkach, gdy miałbyś obliczać wartość oczekiwaną? Zapewne obliczanie wartości oczekiwanej prowadziłaby do kopii kodu metody testowanej, więc test traci sens.
Pierwsze podejście jest wygodne, ale ma małe zastosowanie praktyczne.

2

Staraj sie nie obliczac nic wewnatrz testow (zadnych wartosci oczekiwanych), masz wywolac testowana metode z okreslonymi argumentami i sprawdzic czy oczekiwana wartosc/zachowanie jest takie jak okresliles.

0

A jeszcze jedno, źle używasz asercji!
Powinno być:

const double MachineEpsilon = 2.22044604925e-16;
Assert.AreEqual(expected, result, (Math.Abs(first)+Math.Abs(second))*MachineEpsilon);
1

BTW tak duża ilość testcase'ów jest niepotrzebna. Wyrzuć wszystkie redundantne, przetestuj prawidłowe działanie i przypadki brzegowe (dodawanie liczb skrajnie dużych i skrajnie małych i ich kombinacji), pozostanie Ci z pięć-sześć przypadków i tyle wystarczy.

0

@ŁF ogólnie masz rację ale jest jeden wyjątek od tej reguły, tzw teorie w których podaje się tablicę dla każdego z parametrów metody a biblioteka testująca wywołuje metodę dla wszystkich możliwych kombinacji parametrów. Z tego co rozumiem tą ideę stosuje się je gdy pisze się testy do już istniejących jednostek kodu. Pozwalają one znaleźć kombinacje parametrów których twórca nie wziął po uwagę podczas pisania jednostki.
Niestety zawodowo nie mam za dużo okazji do stosowania TDD, a tym bardziej nie weryfikowałem jeszcze żadnej teorii :).

0
szogun1987 napisał(a):

@ŁF ogólnie masz rację ale jest jeden wyjątek od tej reguły, tzw teorie w których podaje się tablicę dla każdego z parametrów metody a biblioteka testująca wywołuje metodę dla wszystkich możliwych kombinacji parametrów. Z tego co rozumiem tą ideę stosuje się je gdy pisze się testy do już istniejących jednostek kodu. Pozwalają one znaleźć kombinacje parametrów których twórca nie wziął po uwagę podczas pisania jednostki.

W tej sytuacji lepiej zapuścić jakiś automat (np. coś w stylu Pex), aby przeanalizował składnię i wykrył te kombinacje.

Niestety zawodowo nie mam za dużo okazji do stosowania TDD, a tym bardziej nie weryfikowałem jeszcze żadnej teorii :).

Współczuję... Ale jak to jest możliwe? :|

1 użytkowników online, w tym zalogowanych: 0, gości: 1