Inżynieria Oprogramowania
Testy Jednostkowe
Wydział Mechaniczny Politechniki Krakowskiej
Instytut Informatyki Stosowanej
Rok Akademicki 2011/2012, Grupa 13K3
Rafał Polak 13k3
07-11-2011
Sprawozdanie z Laboratorium Komputerowego nr.2
Testy Jednostkowe
1. Ogólne informacje
TESTY JEDNOSTKOWE
- to w programowaniu metoda testowania tworzonego
oprogramowania poprzez wykonywanie testów weryfikujących poprawnośd działania
pojedynczych elementów (jednostek) programu - np. metod lub obiektów w
programowaniu obiektowym lub procedur w programowaniu proceduralnym.
Testowany fragment programu poddawany jest testowi, który wykonuje go i
porównuje wynik (np. zwrócone wartości, stan obiektu, wyrzucone wyjątki) z
oczekiwanymi wynikami - tak pozytywnymi, jak i negatywnymi (niepowodzenie
działania kodu w określonych sytuacjach również może podlegad testowaniu).
Zaletą testów jednostkowych jest możliwośd wykonywania na bieżąco w pełni
zautomatyzowanych testów na modyfikowanych elementach programu, co
umożliwia często wychwycenie błędu natychmiast po jego pojawieniu się i szybką
jego lokalizację zanim dojdzie do wprowadzenia błędnego fragmentu do programu.
Testy jednostkowe są również formą specyfikacji. Z powyższych powodów są
szczególnie popularne w programowaniu ekstremalnym.
2. Cel Ćwiczenia
Celem dwiczenia jest zapoznanie się z możliwością tworzenia testów do pisanych programów w
programie Microsoft Visual Studio w języku C#. Stworzone poniżej testy są prostym przykładem w
celu zweryfikowania poprawności działania pojedynczego elementu i późniejszego ich
odwzorowywania w pisanych projektach.
3. Realizacja Testów
Utworzenie projektu w Microsoft VS o nazw ie Kalkulator
Implementacja Przykładowej Klasy „Kalkulator” w projekcie r ealizującej funkcjonalnośd
dodawania i dzielenia w raz z obsługą w yjątków .
Utworzono nową klasę MyStringMath zawierającą dwie metody statyczne Add i
Devide kolejno definiujące dodawanie oraz dzielenie.
namespace
Kalkulator
{
public
static
class
MyStringMath
{
public
static
string
Add(
string
valt1,
string
valt2)
{
double
value1;
double
value2;
if
(!
double
.TryParse(valt1,
out
value1))
return
"The 1st input value is invalid."
;
if
(!
double
.TryParse(valt2,
out
value2))
return
"The 2nd input value is invalid."
;
return
(value1 + value2).ToString();
}
public
static
string
Devide(
string
valt1,
string
valt2)
{
double
value1;
double
value2;
if
(!
double
.TryParse(valt1,
out
value1))
return
"The 1st input value is invalid."
;
if
(!
double
.TryParse(valt2,
out
value2))
return
"The 2nd input value is invalid."
;
if
(value2 == 0)
return
"Nie dziel przez zero"
;
return
(value1 / value2).ToString();
}
public
static
string
error()
{
throw
(
new
DivideByZeroException
());
}
}
}
Formatka Programu zawiera dwa buttony odpowiadające za dodawanie lub dzielenie oraz
dwa textboxy pozwalające wpisanie dwóch liczb, na których wykonywane będą działania
matematyczne.
Oprogramowanie For matki zaw iera wywołanie metod zawartych w ww klasie po
odpowiednim wciśnięciu przycisku zawartego w format ce:
namespace
Kalkulator
{
public
partial
class
Form1
:
Form
{
public
Form1()
{
InitializeComponent();
}
private
void
label1_Click(
object
sender,
EventArgs
e)
{
}
private
void
Dodawanie_Click(
object
sender,
EventArgs
e)
{
wynik.Text =
MyStringMath
.Add(textBox1.Text, textBox2.Text);
}
private
void
Dzielenie_Click(
object
sender,
EventArgs
e)
{
wynik.Text =
MyStringMath
.Devide(textBox1.Text, textBox2.Text);
}
}
}
Stworzenie projektu Testów w solucji, który został połączony relacją z projektem głównym.
Aby dodad dodatkowy projekt do solucji, należy na niej otworzyd menu kontekstowe i
wybrad „Add >> New Project”
Do głównego kodu należy dopisad linię, która zapewnia użycie przestrzeni nazw z projektu
głównego:
using
Kalkulator;
Implementacja Klasy KalkulatorTest
namespace
KalkulatorTest
{
///
<summary>
///
Summary description for UnitTest1
///
</summary>
[
TestClass
]
public
class
UnitTest1
{
public
UnitTest1()
{
//
// TODO: Add constructor logic here
//
}
private
TestContext
testContextInstance;
///
<summary>
///
Gets or sets the test context which provides
///
information about and functionality for the current test run.
///</summary>
public
TestContext
TestContext
{
get
{
return
testContextInstance;
}
set
{
testContextInstance =
value
;
}
}
#region
Additional test attributes
//
// You can use the following additional attributes as you write your tests:
//
// Use ClassInitialize to run code before running the first test in the class
// [ClassInitialize()]
// public static void MyClassInitialize(TestContex t testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
// public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running eac h test
// [TestInitialize()]
// public void MyTestInitialize() { }
//
// Use TestCleanup to run code after each test has run
// [TestCleanup()]
// public void MyTestCleanup() { }
//
#endregion
[
TestMethod
] //Obowiązkowe przy opisaniu klasy testów
public
void
TestMethod1()
{
//string value1 = "2";
//string value2 = "1";
}
[
TestMethod
] //Obowiązkowe przy opisaniu klasy testów
public
void
CanAddToValues()
{
string
value1 =
"2"
;
string
value2 =
"1"
;
string
result =
MyStringMath
.Add(value1, value2);
Assert
.AreEqual(
"3"
, result);
}
[
TestMethod
] //Obowiązkowe przy opisaniu klasy testów
public
void
TestMethod2()
{
string
value1 =
"10"
;
string
value2 =
"2"
;
string
result =
MyStringMath
.Devide(value1, value2);
Assert
.AreEqual(
"5"
, result);
}
[
TestMethod
] //Obowiązkowe przy opisaniu klasy testów
[
ExpectedException
(
typeof
(
DivideByZeroException
))] //Niezbędne jest określenie typu
wyjątku rzucanego przez klase
public
void
TestError()
{
string
value1 =
"1"
;
string
value2 =
"0"
;
string
result =
MyStringMath
.div(value1, value2);
Assert
.AreEqual(
"Nie dziel przez ZERO!!!"
, result);
}
}
}
4. Rezultat i Wniosek
Po stworzeniu programu należy przejśd pozytywnie przez wszystkie testy stworzone w
projekcie. W miarę możliwości podczas tworzenia projektu, testy należy zawrzed w każdym
miejscu, gdzie istnieje możliwośd popełnienia błędu.
W celu przejścia przez testy klikamy przycisk „Debug All Test In Solution” lub za pomocą
sekwencji przycisków CTRL+R. Wynik przejścia przez testy powinien odpowiadad poniższemu:
Przejście przez wszystkie wyjątki zostało wykonane bezbłędnie
Jeżeli natomiast wywołanie testu nie przejdzie, zwróci Failed należy wnieśd poprawki w kod
programu, zakładając, iż sam test został poprawnie przeprowadzony. Przykładem niepoprawnego
wykonania testu jest:
public
void
CanAddToValues()
{
string
value1 =
"2"
;
string
value2 =
"1"
;
string
result =
MyStringMath
.Add(value1, value2);
Assert
.AreEqual(
"2"
, result);
}
Test nie przeszedł ponieważ oczekiwano wartości 2 w wyniku, natomiast suma (1+2) jest
równa 3.
Po odpowiednim przeliczeniu poprawności wyniku test sprawdzi wynik zwracany przez
program z wynikiem, przez nas wprowadzonym i jeżeli poprawnie dodamy dwie liczby test przejdzie.
Podobnie jest z testem sprawdzającym dzielenie przez zero. Gdy zrobimy go na zmiennych
double test przejdzie, ponieważ nie wie jakiego typu wyjątku się spodziewamy.
Aby test działał poprawnie należy zdefiniowad rodzaj wyjątku dodając linię przed wyjątkiem
ExpectedException
(
typeof
(
DivideByZeroException
))
Wynikiem działania programu są niżej wymienione zrzuty ekranu przedstawiające
funkcjonalności.
Wynik działania dodawania, bez wyrzucania wyjątku
Wynik działania dzielenia, bez wyrzucania wyjątku
Rzut wyjątkiem przy próbie dzielenia przez zero
Podsumowując działanie unit testów ściśle związane jest z metodą wprowadzania zmiennych i
określaniem jakiego wyjątku można się spodziewad w danym fragmencie kodu. Poprawne
przeprowadzenie testów zapobiega późniejszym problemom w projekcie i szybsze napraw ianie
bieżąco pisanego kodu.