Ocena i testowanie kodu
Transkrypt
Ocena i testowanie kodu
Ocena i testowanie kodu
Jacek Starzyński, ZETiIS PW
Treść wykładu
•
●
●
●
●
Jakość oprogramowania, a jakość kodu
Ocena kodu
● metryki
● brzydkie zapachy
Testowanie
● testowanie jednostkowe
● testowanie zależności
● biblioteki do testowania
Ćwiczenia
Jakość oprogramowania
●
Użytkownik: jakość oprogramowania to:
●
●
●
●
zgodność z wymaganiami
przydatność (funkcjonalność, łatwość użycia,
niezawodność)
Wytwórca: ważne są też:
●
konserwowalność
●
rozszerzalność
Użytkownik nie widzi kodu, ale z niego
korzysta, wytwórca musi kod widzieć
(i oceniać)
Ocena kodu - metryki
●
●
●
Metryki służą do obiektywnej, ilościowej
oceny kodu
Można oceniać
●
pojedynczą metodę
●
pojedynczą klasę
●
cały system
Najważniejsze są metryki oceniające
system – ale inne też są istotne
Ocena złożoności metody
●
●
●
Metryka SLOC
Source Lines Of Code (liczba linii
kodu)
Metryka CP
Comment Percentage (procent
komentarzy)
Złożoność cyklomatyczna McCabe
Metryka SLOC
#include <stdio.h>
●
●
●
Pozwala ocenić
wielkość
systemu
...i raczej tylko to
Problem z
porównywaniem
programów w
różnych
językach
int main() {
printf("Hello World");
return 0;
}
-----------------------------------------------------------------------------000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. HELLOWORLD.
000300
000400*
000500 ENVIRONMENT DIVISION.
000600 CONFIGURATION SECTION.
000700 SOURCE-COMPUTER. RM-COBOL.
000800 OBJECT-COMPUTER. RM-COBOL.
000900
001000 DATA DIVISION.
001100 FILE SECTION.
001200
100000 PROCEDURE DIVISION.
100100
100200 MAIN-LOGIC SECTION.
100300 BEGIN.
100400 DISPLAY " " LINE 1 POSITION 1 ERASE EOS.
100500 DISPLAY "Hello world!" LINE 15 POSITION 10.
100600 STOP RUN.
100700 MAIN-LOGIC-EXIT.
100800 EXIT.
Złożoność cyklomatyczna
McCabe
●
●
Zdefiniowana do oceny programów
strukturalnych (w 1976 roku)
Złożoność funkcji (metody) określana
jest przez liczbę niezależnych ścieżek
w grafie przepływu sterowania
●
CC =E −V 2
lub
CC=d −1
Start
Złożoność cyklomatyczna
McCabe
− V ,d
− V
− E
CC 1 =?
CC 2=?
Stop
Ocena złożoności klasy
●
●
●
●
●
●
●
●
Zestaw metryk CK
Zaproponowane w 1993 (IEEE TSE)
Chidamber, Kemerer, MIT
WMC (Weighted method per class)
DIT (Depth of inheritance tree)
NOC (Number of children)
CBO (Coupling between objects)
RFC (Response for class)
LCOM (Lack of cohesion of methods)
Weighted Methods per Class
●
WMC jest sumą złożoności wszystkich
metod klasy
n
●
WMC =∑i=1 c i
●
●
n – liczba metod klasy
●
ci – złożoność i-tej metody
●
●
●
Ocena złożoności klasy = pracochłonności
wymaganej do jej utworzenia i pielęgnacji.
Wysoka dla klas mocno wyspecjalizowanych
Depth of Inheritance Tree
●
DIT jest maksymalną głębokością
położenia klasy w drzewach
dziedziczenia
DIT =max h
●
●
●
●
Klasa może w ogólności (np. C++) dziedziczyć
po kilku hierarchiach. DIT jest najgłębszym z
możliwych poziomem.
Im wyżej klasa dziedziczy, tym jest bardziej
złożona i trudniej przewidzieć jej
zachowanie.
Number of Children
●
NOC jest liczbą bezpośrednich dzieci
klasy w drzewie dziedziczenia
●
●
●
●
●
Im więcej podklas tym większa powtórna
używalność kodu.
Zbyt wiele podklas może świadczyć o złym
wykorzystaniu dziedziczenia (zła
hierarchia?)
Im większy NOC tym większy wpływ ma klasa
na system i tym trudniej ją testować.
Coupling Between Objects
●
CBO jest liczbą klas związanych z
daną przy pomocy innej relacji, niż
dziedziczenie
●
Duża wartość CBO świadczy o dużym
powiązaniu, co zwykle oznacza kłopoty:
●
●
●
●
mała re-używalność
duża wrażliwość na zmiany
trudne testowanie
Response For Class
●
RFC moc zbioru wszystkich metod, które mogą być
wywołane w odpowiedzi na komunikat wysłany do
klasy
RFC =∣{ M } ∪all i { Ri }∣
●
●
●
●
●
{M} – zbiór metod klasy
{Ri} – zbiór metod wywoływanych prze i-tą
metodę klasy
Im większe RFC tym bardziej funkcjonalna i bardziej
złożona (trudna do testowania) klasa.
Lack of Cohesion of Methods
●
LCOM to różnica pomiędzy mocą zbioru par metod
odwołujących się do rozłącznych podzbiorów
atrybutów a mocą zbioru par metod odwołujących
się do przecinających się podzbiorów atrybutów.
LCOM =max ∣P∣−∣Q∣ ,0
P = M i , M j : I Mi ∩ I Mj =∅
Q= M i , M j : I Mi ∩I Mj ≠∅
●
●
●
●
●
●
M – zbiór metod klasy
IMi – atrybuty klasy, do których odwołuje się
metoda
Lack of Cohesion of Methods
●
LCOM (wg def. zaproponowanej przez HendersonaSellersa w 1996 roku) to względna liczba metod nie
odwołujących się do atrybutów klasy
●
●
●
●
●
●
●
1 a
m− ∑i=1 mi
a
LCOM H =
m−1
m – liczba metod,
a – liczba atrybutów
mi – liczba metod, które używają i-tego
atrybutu
LCOMH > 1 = problem
Wykorzystanie metryk CK
do oceny systemu
●
Słaby kod gdy:
●
RFC ≈ WMC + CBO
● duże DIT
● duże LCOM
●
●
●
V.Lang, C.Coleman, NASA
Ocena złożoności systemu
●
Zestaw metryk MOOD (F. Brito e Abreu,
1995)
●
●
●
●
Ocena całego systemu
Procentowe miary wykorzystania
mechanizmów obiektowości
Niezależny od języka, wielkości
systemu
Zweryfikowany doświadczalnie
MOOD
●
Hermetyzacja
●
●
●
Dziedziczenie
●
●
●
MIF Method Inheritance Factor
AIF Attribute Inheritance Factor
Polimorfizm
●
●
MHF Method Hiding Factor
AHF Attribute Hiding Factor
PF Polymorphism Factor
Powiązania
●
CF Coupling Factor
MOOD: miary hermetyzacji - AHF
●
AHF Attribute Hiding Factor
c
AHF =1−
●
●
∑k =1
∑ j≠k A
j
k
c−1
c
∑k=1 Ak
c – liczba klas
Ak – liczba atrybutów w k-tej klasie
Akj – liczba atrybutów k-tej klasy widocznych w j-tej
klasie
MOOD: miary hermetyzacji - MHF
●
MHF Method Hiding Factor
c
MHF =1−
●
●
∑k =1
∑ j≠k M
j
k
c−1
c
∑k =1 M k
c – liczba klas
Mk – liczba metod w k-tej klasie
Mkj – liczba metod k-tej klasy widocznych w j-tej
klasie
Wartości xHF
●
●
●
●
e Abreu przeanalizował AHF i MHF dla
8 dużych projektów o otwartym kodzie
AHF zawierał się w przedziale
67% (MFC) – 96% (Motif )
MHF zawierał się w przedziale
10% (ET++) – 37 % (Motif)
Wnioski wydają się dość oczywiste:
trzeba ukrywać dane, nie można
ukryć wszystkich metod
MOOD: miary dziedziczenia - AIF
●
AIF Attribute Inheritance Factor
c
AIF =
●
●
i
∑k =1 Ak
c
∑k =1 Ak
c – liczba klas
Ak – liczba wszystkich atrybutów w k-tej klasie
Aki – liczba odziedziczonych atrybutów k-tej klasy
MOOD: miary dziedziczenia - MIF
●
MIF Method Inheritance Factor
c
MIF =
●
●
i
∑k =1 M k
c
∑k =1 M k
c – liczba klas
Mk – liczba wszystkich metod w k-tej klasie
Mki – liczba odziedziczonych metod k-tej klasy
Wartości xIF
●
●
●
●
e Abreu przeanalizował AIF i MIF dla 8
dużych projektów o otwartym kodzie
AIF zawierał się w przedziale
40% – 70%
MIF zawierał się w przedziale
64% – 85 %
Jest to oczekiwane, ale wnioski nie są
w tym przypadku tak oczywiste
MOOD: miara polimorfizmu - PF
●
PF Polymorphism Factor
c
o
k
∑k=1 M
PF = c
n
∑k =1 [ M k⋅S k ]
●
c – liczba klas
Mko – liczba przesłaniających metod w k-tej klasie
●
Mkn – liczba nowych method k-tej klasy
●
Sk – liczba podklas k-tej klasy
Wartości PF
●
●
●
●
e Abreu przeanalizował PF dla 8
dużych projektów o otwartym kodzie
PF zawierał się w przedziale 3% – 13%
Można przypuszczać, że świadczy to
słabym (jeszcze wtedy) wykorzystaniu
polimorfizmu
Niektóre źródła zalecają > 10%, ale
sprawa jest kontrowersyjna
MOOD: miara powiązań - CF
●
CF Coupling Factor
c
∑k =1 C k
CF =
c
2
c −c−2 ∑k=1 S k
●
●
c – liczba klas
Ck – liczba klas-klientów k-tej klasy
Sk – liczba podklas k-tej klasy
Wartości CF
●
●
●
e Abreu przeanalizował CF dla 8
dużych projektów o otwartym kodzie
CF zawierał się w przedziale 5% – 20%
Wydaje się, że pożądane wartości to
przedział 5-15%:
●
●
zbyt mało: odpowiedzialność jest zbyt
skupiona
zbyt dużo: system jest mało elastyczny
Przykłady
●
MFC
Motif
● MHF
24.6%
39.2%
● AHF
68.4%
100.0%
● MIF
83.2%
64.3%
● AIF
59.6%
50.3%
● PF
2.7%
GNU
ET++
13.3%
9.6%
84.1%
69.4%
63.1%
83.9%
62.6%
51.8%
3.5%
4.5%
Ocena kodu: narzędzia
●
http://www.mccabe.com/
●
http://www.msquaredtechnologies.c
om/
Testowanie
●
Po co testować?
●
Co testować?
●
Kiedy testować?
●
Jak testować?
●
Narzędzia
Po co testować?
●
Testy nie udowadniają poprawności...
●
...ale pozwalają wykryć błędy
●
●
Testy są ważnym narzędziem
przyrostowej budowy
oprogramowania
Testy są niezbędnym narzędziem
konserwacji oprogramowania
Co testować?
●
Konstrukcję klasy – testy jednostkowe
●
Architekturę systemu – testy integracji
●
Wypełnianie wymagań – testy systemu
●
●
Zachowanie systemu – testy integracji
systemu
Nerwy zamawiającego – testy akcepujące
Co testować?
Źródłó: http://www.methodsandtools.com/archive/archive.php?id=13
Kiedy testować?
●
Jak najwcześniej
●
●
●
Projektowanie testów razem z testowanym
kodem (a nawet wcześniej) pozwala
dopracować funkcjonalność kodu.
Wczesne testowanie jest łatwiejsze i szybsze.
Jak najczęściej
●
Zwłaszcza przy zmianach w kodzie – częste
testy są łatwiejsze i skuteczniejsze.
Jak testować?
●
Automatycznie czy ręcznie?
●
●
●
Automatycznie = łatwo => często
ręczne testowanie może być bardziej
wszechtronne, ale bywa zawodne – ludzie
są leniwi.
Zwinnie, czy tradycyjnie?
●
●
Eksploracyjnie czy skryptowo?
Narzędzia
●
Odpowiednia składnia języka
●
●
●
np. metoda main w Javie
Biblioteki do testowania jednostkowego
●
xUnit: SUnit, JUnit,...
●
JUnitX
●
JTiger
●
TestNG
Narzędzia do zarządzania kodem
Biblioteka JUnit
●
●
●
●
Narzędzie do testowania
jednostkowego w Javie
Stworzona przez K. Becka i E. Gammę
jest najbardziej (u|zna)danym
członkiem rodziny xUnit
Stosunkowo stara i niewygodna...
ale ciągle jeszcze bardzo popularna
JUNIT – podstawowe klasy
Test
<<interface>>
TestResults
TestCase
MyTest
TestSuite
JUNIT – przykład
import java.util.*;
public class MathUtl {
public double avr( List<Double> l ) {
double s= 0;
for( double x : l )
s+= l;
return s / l.size();
}
}
import junit.framework.*;
import java.util.*;
public class MathUtlTest extends TestCase {
public void testAverage2 () {
Vector<Double> nums = new Vector<Double>();
nums.add(3.0);
nums.add(13.5);
assertTrue( MathUtl.avr(nums) == 8.25);
}
}
Struktura katalogów
| `
|-- src
| `-- contact
|
|-- BusinessContact.java
|
|-- Contact.java
|
|-- ExGui.form
|
|-- ExGui.java
|
|-- PhoneBook.java
|
`-- PhoneBookUtils.java
`-- test
`-- contact
|-- BusinessContactTest.java
|-- ContactTest.java
`-- PhoneBookTest.java
JUNIT – kompilacja i
uruchamianie
$ javac -cp /opt/junit/org.junit_3.8.1/junit.jar MUT.java MathUtl.java
$ java -cp /opt/junit/org.junit_3.8.1/junit.jar:. junit.textui.TestRunner MUT
...
Time: 0,006
OK (3 tests)
$ java -cp /opt/junit/org.junit_3.8.1/junit.jar:. junit.swingui.TestRunner MUT
JUNIT – struktura klasy testującej
●
●
●
●
konstruktor jest zwykle pomijany
public class MyTest
extends TestCase {
void setUp() {
...
}
metoda setUp() służy do
inicjalizacji i jest wywoływana
przed każdym testem
metoda tearDown() sprząta i
jest wywoływana po każdym
teście
przypadki testowe są
implementowane w postaci
metod testCośTam()
void tearDown() {
...
}
void testOne() {
...
}
...
void testXXX() {
...
}
}
JUNIT – metoda testująca
public class JOWTest extends TestCase {
private JOW jow = null;
public void setUp() {
jow= new JOW( "Warszawa", 2000000 );
}
public void testToString() {
String s= jow.toString();
assertEquals(
"JOW Warszawa: liczba wyborców: 2000000, głosowało: 0", s );
}
public void tearDown() {
jow= null;
}
}
Rodzaje assercji
●
assertTrue( [komunikat], warunek )
●
assertFalse( [komunikat], warunek )
●
assertNull( [komunikat], referencja )
●
assertNotNull( [komunikat], referencja )
●
assertSame( [komunikat], oczekiwana, faktyczna )
●
assertNotSame( [komunikat], oczekiwana, faktyczna )
●
assertEquals( [komunikat], oczekiwana, faktyczna )
●
assertEquals( [komunikat], oczekiwana, faktyczna,delta )
●
assertNotEquals( [komunikat], oczekiwana, faktyczna )
●
fail( [komunikat] )
Inicjowanie obiektów
Nie w konstruktorze!
public class JOWTest extends TestCase {
private JOW jow = null;
public JOWTest( String testName ) {
super( testName );
Obiekt jow nie zostanie utworzony
jow = new JOW( null, 0 );
(w wyniku zgłoszenia wyjątku
przez konstruktor klasy JOW).
}
...
}
Wyjątek zostanie przechwycony
przez środowisko Junit,
ale komunikat będzie niepełny,
a więc mylący.
Inicjowanie obiektów
W metodzie setUp()
public class JOWTest extends TestCase {
private JOW jow = null;
Zgłoszenie wyjątku zaowocuje
prawidłowym, jasnym komunikatem.
public setUp( ) {
jow = new JOW( null, 0 );
java}-cp /opt/eclipse/plugins/org.junit_3.8.1/junit.jar:.
junit.textui.TestRunner JOWTest
.E
Time: 0,021
There was 1 error:
1) testToString(JOWTest)java.lang.IllegalArgumentException: JOW: Złe wywołanie konstruktora
at JOW.<init>(JOW.java:8)
at JOWTest.setUp(JOWTest.java:8)
...
}
FAILURES!!!
Tests run: 1,
Failures: 0,
Errors: 1
Kolejność wykonywania testów
public class JOWTest extends TestCase {
testThisBefore() {
...
}
testThisAfter() {
...
}
}
To nie zadziała
- Przypadki testowe są wykonywane
w losowej kolejności
- Nie mogą miec efektów ubocznych
Kolejność wykonywania testów
public class JOWTest extends TestCase {
public JOWTest( String name ) {
super( name );
}
public void testJeszczePozniej() { System.out.println( "JeszczePozniej" ); }
public void testPotem() { System.out.println( "Potem" ); }
public void testNajpierw() { System.out.println( "Najpierw" ); }
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest( new JOWTest( "testNajpierw" ) );
suite.addTest( new JOWTest( "testPotem" ) );
suite.addTest( new JOWTest( "testJeszczePozniej" ) );
return suite;
}
...
Zewnętrzne zasoby
public class MyClassTest extends TestCase {
....
public void setUp() {
InputStream data= new FileInputStream( "/var/lib/testdata.txt" );
....
}
...
Brak danych testowych (np. w innym środowisku)
może generować mylące komunikaty.
Wewnętrzne zasoby
w kodzie
public class MyClassTest extendsDane
TestCase
{
testującym
....
private double daneTestowe[] = { 1., 3., 5., 7., 13. };
public void setUp() {
InputStream data= this.getClass().getResourceAsStream(
"mojeDaneTestowe.dat" );
....
}
...
Dane pobierane za pośrednictwem class loadera
Testy powinny być niezależne
od kontekstu
public class MyClassTest extends TestCase {
....
public void testLocale() {
Locale l= Locale.getDefault();
assertEquals( "Fri Jun 08 09:07:09 GMT 2007",
new Date().toString() );
}
}
...
Nie można oczekiwac określonej daty,
czy nawet jej formatu
Testy nie powinny
obsługiwać wyjątków
public class MyClassTest extends TestCase {
....
public void testTestNullData() {
try {
myClassObject.method( null, null );
} catch( NullPointerException e ) {
fail( "Przechwycono wyjątek" );
}
}
}
...
Przechwycenie wyjątku nie pozwala
zdiagnozować jego przyczyny
Testowanie wyjątków
public class MyClassTest extends TestCase {
....
public void testTestNullData() {
try {
myClassObject.method( null, null );
fail( "Oczekiwano NullPointerException" );
} catch( NullPointerException e ) {
// jest ok!
}
}
}
...
Wyjątek powinien być zgłoszony,
a więc jego brak jest błędem.
Testowanie wyjątków
public class MyClassTest extends TestCase {
public void testNullData() {
myClassObject.method( null, null );
}
}
public static Test suite() {
TestSuite s= new testSuite();
s.addTest( new ExceptionTestCase( "testNullData",
NullPointerException.class );
return s;
}
Specjalna klasa dimplementująca
logikę odwracania wyjątku.
Wady Junit 3.x
●
konieczność dziedziczenia po TestCase
●
sztywne konwencje nazewnicze
●
niewygodne kontrolowanie kolejności
testów
●
tylko wspólna inicjacja i finalizacja
●
ograniczona funkcjonalność
Rozszerzenia
●
●
●
JUnitX – nacisk na testowanie
składowych prywatnych
JUnit 4.0 – wykorzystanie nowych
możliwości Javy 5.0
TestNG – oddzielna od implementacji
konfiguracja testów
JUnitX - Testowanie metod
prywatnych
(http://www.extreme-java.de/junitx/)
public class JOWTest extends PrivateTestCase {
...
public void testGlosuje()
throws TestAccessException
{
jow.glosuje( 100 );
int g= getInt( jow, "glosowalo" );
assertEquals( 100, g );
}
public class JOW {
private String nazwa;
private int liczbaWyborcow;
private int glosowalo;
...
JUnitX – uruchamianie testów
import junit.framework.*;
import junitx.framework.*;
public class TestPackage
implements junitx.framework.TestPackage
{
static public Test suite () {
TestSuite suite = new TestSuite ("JOW tests");
suite.addTestSuite (JOWTest.class);
return suite;
}
}
JUnitX – pośrednik
import java.lang.reflect.*;
import junit.framework.*;
import junitx.framework.*;
public class TestProxy
extends junitx.framework.TestProxy {
public Object newInstance (Object[] anArgList)
throws TestAccessException {
try
{
return
getProxiedClass ().getConstructor (
anArgList).newInstance (anArgList);
} catch (Exception e) {
throw new TestAccessException (
"could not instantiate " + getTestedClassName (), e);
}
}
...
●
klasy testowe to POJO
●
wykorzystanie anotacji
●
JUnit 4.0
metody inicjujące/sprzątające związane z
konkretnym testem
●
wbudowana obsługa wyjątków
●
sterowanie zbiorem wykonywanych testów
●
obsługa limitów czasowych
●
kompatybilność z JUnit 3.x (dwustronna)
Zastosowanie JUnit 4.x
import org.junit.*;
import static org.junit.Assert.*;
......
public class JOWT4 {
@Before
public void makeJOW() {
jow= new JOW( ... );
}
private JOW jow = null;
@Test
public void testToString() {
String s= jow.toString();
assertEquals( .... );
}
....
}
@After
public void destroyJOW() {
jow= null;
}
Kompilacja i uruchomienie testów
$ javac -cp junit4.3.1/junit-4.3.1.jar JOW.java JOWT4.java
$ java -cp junit4.3.1/junit-4.3.1.jar:. org.junit.runner.JUnitCore JOWT4
JUnit version 4.3.1
...
Time: 0,052
OK (3 tests)
Anotacje Junit 4
●
@BeforClass
●
@AfterClass
●
@Ignore
●
@Test(timeout=1000)
●
@Test(expected=MyException)
http://testng.org/
TestNG
Testing, the Next Generation
●
klasy testowe to POJO
●
wykorzystanie anotacji
●
metody inicjujące/sprzątające związane z
konkretnym testem, grupą, klasą
●
parametryzacja przypadków testowych
●
zależności pomiędzy przypadkami
●
...
http://testng.org/
TestNG
Testing, the Next Generation
●
...
●
wbudowana obsługa wyjątków
●
sterowanie zbiorem wykonywanych
testów, także przez zewnętrzny plik
●
wykorzystanie programowych asercji Javy
●
obsługa limitów czasowych
Anotacje TestNG
●
●
●
●
●
●
●
●
●
●
●
@Test
wybrane parametry:
alwaysRun (nawet, gdy zależy od metody, która padła)
dataProvider (skąd dane)
dataProviderClass (gdzie szukać dataProvidera)
dependsOnGroups (lista grup)
dependsOnMethods (lista metod)
description
enabled
expectedExceptions
groups
timeOut
Konfiguracyjne anotacje TestNG
●
●
●
●
●
●
●
●
●
●
@BeforeSuite
@AfterSuite
@BeforeTest
@AfterTest
@BeforeGroups
@AfterGroups
@BeforeClass
@AfterClass
@BeforeMethod
@AfterMethod
●
Parametry:
●
alwaysRun
●
dependsOnGroups
●
dependsOnMethods
●
enabled
●
groups
●
inheritGroups
Inne anotacje TestNG
●
●
●
@DataProvider -> Object[][]
parametr name
@Factory -> Object[]
@Parameters
parametr value
Przykład
@DataProvider(name = "test1")
public Object[][] createData1() {
return new Object[][] {
{ "Cedric", new Integer(36) },
{ "Anne", new Integer(37)},
};
}
@Test(dataProvider = "test1")
public void verifyData1(String n1, Integer n2) {
System.out.println(n1 + " " + n2);
}
Uruchamianie testów
●
z linii poleceń
java org.testng.TestNG testng1.xml [testng2.xml
testng3.xml ...]
●
przy pomocy anta
●
przez IDE / pluginy do IDE
Konfiguracja testów
public class Test1 {
@Test(groups = { "functest", "checkintest" })
public void testMethod1() {
}
@Test(groups = {"functest", "checkintest"} )
public void testMethod2() {
}
@Test(groups = { "functest" })
public void testMethod3() {
}
}
<test name="Test1">
<groups>
<run>
<include name="functest"/>
</run>
</groups>
<classes>
<class name="example1.Test1"/>
</classes>
</test>
Konfiguracja testów, cd
@Test
public class Test1 {
@Test(groups = { "windows.checkintest" })
public void testWindowsOnly() {
}
@Test(groups = {"linux.checkintest"} )
public void testLinuxOnly() {
<test
}
}
@Test(groups = { "windows.functest" )
public void testWindowsToo() {
}
name="Test1">
<groups>
<run>
<include name="windows.*"/>
</run>
</groups>
<classes>
<class name="example1.Test1"/>
</classes>
</test>
Konfiguracja testów, cd
@Parameters({ "first-name" })
@Test
public void testSingleString(String firstName) {
System.out.println("Invoked testString " + firstName);
assert "Cedric".equals(firstName);
}
<suite name="My suite">
<parameter name="first-name" value="Cedric"/>
<test name="Simple example">
<-- ... -->
Ćwiczenie
•
• Proszę pobrać niezbędne pliki z
http://www.iem.pw.edu.pl/~jstar/dyd/java/jun
it/
• i napisać klasę testową dla JOW z
wykorzystaniem Junit3.8, Junit4.3, JUnitX.
•
• Przykładowe szkielety do JunitX i Junit4 są
dostępne w katalogu podanym wyżej.
•
•