Unit testing-ul s-a impus în ultima perioadă în dezvoltarea proiectelor scrise în limbajul Java şi nu numai, pe măsura apariţiei unor utilitare gratuite de testare a claselor, care au contribuit la creşterea vitezei de programare şi la micşorarea semnificativă a numărului de bug-uri.
Printre avantajele folosirii framework-ului JUnit se numără:
Reprezintă un framework de Unit Testing pentru Java.
Exemplu:
public class Student { private String name; private String age; public Student(String name, String age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } }
import java.util.ArrayList; import java.util.List; public class Group { List<Student> students; Group () { students = new ArrayList<Student>(); } public List<Student> getStudents() { return students; } public void setStudents(List<Student> students) { this.students = students; } public void addStudent(Student student) { students.add(student); } public Student getStudent(String name) { for (Student st : students) { if (null != st.getName() && st.getName().equals(name)) { return st; } } return null; } public boolean areStudentsInGroup() { if (0 == students.size()) { return false; } return true; } }
import org.junit.jupiter.api.* public class GroupTest { private Group group; @BeforeEach public void setup() { group = new Group(); } @Test public void testNoStudentInGroup() { Assertions.assertEquals(false, group.areStudentsInGroup()); } @Test public void testAddStudent() { Student st = new Student("Elena", "11"); group.addStudent(st); Assertions.assertTrue(group.getStudent("Elena").equals(st)); } @AfterEach public void tearDown() { group = null; } }
Observaţii:
@Test
@BeforeEach
) şi tearDown (având adnotarea: @AfterEach
) se apelează înainte, respectiv după fiecare test. Se întrebuinţează pentru iniţializarea/eliberarea resurselor ce constituie mediul de testare, evitându-se totodată duplicarea codului şi respectându-se principiul de independenţă a testelor. Pentru exemplul dat ordinea este:@BeforEach setUp
@Test testNoStudentInGroup
@AfterEach tearDown
@BeforeEach setUp
@Test testAddStudent
@AfterEach tearDown
ParentTest @BeforeEach setUp
ChildTest @BeforeEach setUpSub
ChildTest @Test testChild1
ChildTest @AfterEach tearDownSub
ParentTest @AfterEach tearDown
assert
:assertTrue
assertFalse
assertEquals
assertNull
/ assertNotNull
Câteodată avem nevoie să testăm funcționalitatea unor clase ce folosesc metode din alte clase netestate sau care nu pot fi testate. De asemenea, există cazuri în care vrem sa testăm comportamentul clasei în situații extreme sau foarte greu de replicat (erori de disc, epuizarea spațiului pe disc, obținerea unei anumite valorii în cazul in care folosim generatoare random).
Pentru a rezolva ușor aceste necesități putem folosi obiecte de tip mock. Aceste obiecte simulează comporatamentul clasei mock-uite și sunt controlate din interiorul unit testelor. Pentru mai multe detalii puteți consulta pagina Mock Object.
Animal
şi clasa Zoo
. Clasa Zoo
conţine un vector de animale. Implementaţi metodele: addAnimal(Animal a)
, removeAnimal(Animal a)
, boolean areAnimals(), getAnimals()
, size()
. Creaţi o clasa Test
unde veţi verifica diverse scenarii:Zoo
.testAddAnimal
- adaugă un obiect Animal
şi verifică daca adăugarea a avut loc cu succes. Folosiţi: assertEquals
testRemoveAnimal
- folosiţi assertTrue
testAreAnimalsInZoo
- testul pică dacă metoda returnează false
. Hint: Assert.fail()
testGetAnimals
- adăugaţi două obiecte Animal
. Verificaţi ca adăugarea a avut loc cu succes. Folosiţi assertFalse.GeometricForms
avand un constructor ce primeste un String ce poate fi unul din valorile enum-ului Forms
.isTriangle
, isCircle
si isRectangle
au drept scop evaluarea stării obiectului GeometricForms
.GeometricFormsTest
.public enum Forms { TRIANGLE, CIRCLE, RECTANGLE }