Test jednostkowy (ang. unit test) to technika testowania tworzonego oprogramowania poprzez wykonywanie testów weryfikujących poprawność działania pojedynczych elementów (jednostek) programu - np. metod, obiektów.
Testowany fragment programu poddawany jest testowi, który wykonuje go i porównuje wynik z oczekiwanymi wynikami.
Źródło: pl.wikipedia.org
public class Kalkulator
{
public int Suma(int [] x)
{
if (x == null) throw new ArgumentNullException();
int s = 0;
for(int i=1; i < x.Length ; i++) s+=x[i];
return s;
}
}
public class KalkulatorTest
{
public void SumaTest()
{
int[] x = { 1, 2, 3, 4 };
Kalkulator c = new Kalkulator();
int oczekiwanyWynik = 10;
int aktualnyWynik = c.Suma(x);
if (aktualnyWynik != oczekiwanyWynik)
throw new Exception($"Test oblany: spodziewana wartosc {oczekiwanyWynik}, aktualna wartosc {aktualnyWynik}");
}
}
public class KalkulatorTest
{
public void SumaTestException()
{
Kalkulator c = new Kalkulator();
try {
c.Suma(null);
}
catch (ArgumentNullException) {
return;
}
throw new Exception("Test oblany");
}
}
class Program
{
static void Main(string[] args)
{
KalkulatorTest test = new KalkulatorTest();
test.SumaTest();
test.SumaTestException();
Console.WriteLine("Wszystkie testy zaliczone.");
}
}
Porażka
![]() |
Sukces
![]() |
[TestClass]
public class UnitTestKalkulator
{
[TestMethod]
public void TestSuma10()
{
// arrange
int[] x = { 1, 2, 3, 4 };
Kalkulator c = new Kalkulator();
int oczekiwanyWynik = 10;
//act
int aktualnyWynik = c.Suma(x);
//assert
Assert.AreEqual(oczekiwanyWynik, aktualnyWynik);
}
}
Technika zwinna (agile), wywodząca się z programowania ekstremalnego.
Źródło: Test-driven development Wstęp do Test Driven Development (MSDN)
Wzorzec AAA: Arrange → Act → Assert
Narzędzia i biblioteki wspierające tworzenie testów, ich organizację, automatyzację wykonywania, raportowanie
Wikipedia: List of unit testing frameworks
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestClass]
public class UnitTestKalkulator
{
private Kalkulator _calc;
[TestInitialize]
public void Init()
{
_calc = new Kalkulator();
}
[TestMethod]
public void TestSuma10()
{
int[] x = { 1, 2, 3, 4 };
int oczekiwanyWynik = 10;
int aktualnyWynik = _calc.Suma(x);
Assert.AreEqual(oczekiwanyWynik, aktualnyWynik);
}
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void TestSumaException()
{
_calc.Suma(null);
}
}
using NUnit.Framework;
[TestFixture]
public class UnitTestKalkulator
{
private Kalkulator _calc;
[SetUp]
public void Create()
{
_calc = new Kalkulator();
}
[Test]
public void TestSuma10()
{
int[] x = { 1, 2, 3, 4 };
int oczekiwanyWynik = 10;
int aktualnyWynik = _calc.Suma(x);
Assert.AreEqual(oczekiwanyWynik, aktualnyWynik);
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void TestSumaException()
{
_calc.Suma(null);
}
}
using Xunit;
public class KalkulatorTest
{
private Kalkulator _calc;
public KalkulatorTest()
{
_calc = new Kalkulator();
}
[Fact]
public void TestSuma()
{
int[] x = { 1, 2, 3, 4 };
int oczekiwanyWynik = 10;
int aktualnyWynik = _calc.Suma(x);
Assert.Equal(oczekiwanyWynik, aktualnyWynik);
}
[Fact]
public void TestSumaException()
{
Assert.Throws<ArgumentNullException>(() => _calc.Suma(null));
}
}
{2, 4, 70)
dla liczb dodatnich całkowitych {-1, 0, 2, 4, 70)
dla liczb dodatnich całkowitych
Klasa PrivateObject pozwala opakować klasę zawierającą prywatne elementy do testowania. Dostęp do prywatnych elementów za pomocą metody Invoke()
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestMethod]
public void TestPrywatnejMetody()
{
var obj = new PrivateObject(typeof(KlasaZPrywatnąMetodą));
var wynik = obj.Invoke("PrywatnaMetoda");
Assert.AreEqual(wynik, spodziewanyWynik);
}
Szablony projektów: Unit Test Project, Visual C#, C++
![]() | ![]() |
TextContext
(tworzona automatycznie lub należy dodać ręcznie)„xUnit.net is a free, open source, community-focused unit testing tool for the .NET Framework. Written by the original inventor of NUnit v2, xUnit.net is the latest technology for unit testing C#, F#, VB.NET and other .NET languages. xUnit.net works with ReSharper, CodeRush, TestDriven.NET and Xamarin.”
Zaprojektowany z myślą o maksymalnym uproszczeniu testowania
Pakiety NuGet
xUnit.net
framework xunit.runner.console
uruchamianie testów w konsoli xunit.runner.visualstudio
integracja z Test Explorer w VS[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0; Data Source=C:\Data\MathsData.sdf;", "Numbers")]
[TestMethod]
public void AddIntegers_FromDataSourceTest()
{
var target = new Maths();
// Access the data
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]);
int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
int actual = target.IntegerMethod(x, y);
Assert.AreEqual(expected, actual);
}
[Theory]
[InlineData(3)]
[InlineData(5)]
[InlineData(6)]
public void MyFirstTheory(int value)
{
Assert.True(IsOdd(value));
}
bool IsOdd(int value)
{
return value % 2 == 1;
}
}
[Theory]
[PropertyData("SplitCountData")]
public void SplitCount(string input, int expectedCount)
{
var actualCount = input.Split(' ').Count();
Assert.Equal(expectedCount, actualCount);
}
public static IEnumerable<object[]> SplitCountData
{
get
{
// Or this could read from a file. :)
return new[]
{
new object[] { "xUnit", 1 },
new object[] { "is fun", 2 },
new object[] { "to test with", 3 }
};
}
}
Zródło: Theory DDT, Tom DuPont
[Fact(Skip="Trait Extensibility is not working in 1654"), Category("Slow Test")]
public void LongTest()
{
Thread.Sleep(500);
}
[Fact, Trait("Category", "Supa")]
public void LongTest2()
{
Assert.True(true);
}
[Fact(Timeout=50)]
public void TestThatRunsTooLong()
{
System.Threading.Thread.Sleep(250);
}
[TestMethod]
public void IntroductoryTest()
{
// Fixture setup
Fixture fixture = new Fixture();
int expectedNumber = fixture.Create<int>();
MyClass sut = fixture.Create<MyClass>();
// Exercise system
int result = sut.Echo(expectedNumber);
// Verify outcome
Assert.AreEqual<int>(expectedNumber, result, "Echo");
// Teardown
}
[Theory, AutoData]
public void IntroductoryTest(int expectedNumber, MyClass sut)
{
int result = sut.Echo(expectedNumber);
Assert.Equal(expectedNumber, result);
}
public class Client {
// Wewnętrzna referencja do usługi
private Service service;
// Wstrzyknięcie przez konstruktor
Client(Service service) {
this.service = service;
}
// Metoda w której klient korzysta z usługi (chcemy wyizolować to działanie)
public double Compute(double x) {
return x * service.GetSomeValue();
}
}
// Tworzymy obiekt atrapę
var mockClient = new Mock<Service>();
// Ustawiamy metodę aby zwracała symulowaną wartość
mockClient.Setup(mock => mock.GetSomeValue()).Returns(1);
// Wstrzykujemy atrapę do obiektu który będzie testowany
var client = new Clent(mockClient.Object);
// Test
Assert.IsEqual(client.Compute(2), oczekiwanaWartosc);
Pokrycie kodu mierzy, ile procent kodu zostało sprawdzone przez testy jednostkowego. Przyjmuje się, że dobrze napisane testy powinny mieć pokrycie rzędu przynajmniej 70% .
![]() | ![]() |
Testowanie mutacyjne – technika automatycznego badania, na ile dokładnie testy jednostkowe sprawdzają kod programu. Polega na automatycznym wielokrotnym wprowadzaniu małych losowych błędów w programie i uruchamianiu za każdym razem testów jednostkowych, które powinny te błędy wykryć. Testowanie mutacyjne wymaga dużej mocy obliczeniowej i dlatego dopiero od niedawna próbuje się je wykorzystywać w praktyce.
Źródło: pl.wikipedia.pl