Proves de Software (en Java amb JUnit)

  • View
    1.000

  • Download
    2

Embed Size (px)

DESCRIPTION

Apunts de proves unitàries en Java usant JUnit.

Text of Proves de Software (en Java amb JUnit)

  • 1.Proves de software (en Java amb JUnit)Juan Manuel Gimeno Illajmgimeno@diei.udl.cat

2. ndex Qu i per qu dels tests unitaris Com? El framework JUnit (3.x) Proves en allament Tipus de proves dins del cicle de vida2 3. Necessitat dels tests unitaris Quan programem necessitem saber si el que hem construt realment funciona Per tant el que hem de fer s executar els nostres tests d'acceptaci Normalment ho fem per de forma informal: No sn automtics (provem a m) No els repetim (problemes de regressi) No sn focalitzats (provem moltes coses de cop)3 4. Definici de test unitari Un test unitari comprova que un mtode accepta un rang de valor esperats i que retorna els valors esperats per cada valor provat. Per tant el que volem s provar el mtode a travs de la seva especificaci: Si li passem el valor x retornar el valor correcte y? Si li passem el valor z llenar l'excepci prefixada?4 5. Fent tests manualment Suposem que volem testejar la segent classe: public class Calculator {public double add(double number 1, double number2) {return number1 + number 2;}} 5 6. Fent tests manualment Com podem provar aquesta classe? Fem un programa que demani dos nombres i comprovem que el resultat s correcte? Quants nombres entrarem? Si trobem un error i modifiquem el programa, recordarem els que haviem provat abans? La idea s fer un programa que faci aix automticament de manera que es pugui repetir tantes vegaden com calgui!! 6 7. Programant una classe de provapublic class Test Calculator {public static void main (String[] args) {Calculator calculator = new Calculator();double result = calculator.add(10, 50);If (result != 60) { System.out.println(Bad result: + result);}}} S'ha d'estar pendent de la sortida per si hi ha errors A ms la forma convencional d'assenyalar errors en Java sn les excepcions7 8. Millorant la classe de prova Cada prova est public class TestCalculator {implementada enprivate int nbErrors = 0; un mtodepublic void testAdd() {Calculator calculator = new Calculator();double result = calculator.add(10, 50);if (result != 60) {throw new RuntimeException(Bad result: + result);}}public static void main(String[] args) {TestCalculator test = new TestCalculator();try {test.testAdd();Fcil afegir} catch (Throwable e) { noves provestest.nbErrors++;e.printStackTrace();}if (test.nbErrors > 0) {throw new RuntimeException(There were + test.nbErrors + error(s));}}8 } 9. Frameworks de proves unitries Un framework per p.u. ha de seguir un conjunt de bones prctiques Cada test ha d'executar-se de forma independent a tots els altres Els errors s'han de detectar i mostrar test a test Ha de ser fcil poder seleccionar quins tests s'executaran El framework JUnit proveeix de totes aquestes facilitats (i ms) 9 10. El Framework JUnit Proveeix diversos front-ends per mostrar els resultats dels tests (lnia de comanda, awt, swing, ) Classloaders diferents per a cada test per evitar efectes laterals Mtodes estndard per inicialitzar i alliberar recursos (setUp and tearDown) Varietat d'assercions per a comprovar els resultats de les proves Integraci amb IDEs, ant, maven, ....10 11. La prova usant JUnit import junit.framework.TestCase public class TestCalculator extends TestCase { public void testAdd() { Calculator calculator = new Calculator(); double result = calculator.add(10, 50); assertEquals(60, result, 0); } } javac -cp ../junit3.8.2/junit.jar *.java java -cp .:../junit3.8.2/junit.jar junit.swingui.TestRunner TestCalculator 11 12. Nomenclatura de JUnit Test case: Classe que estn TestCase i que cont una o ms proves representades pels mtodes testXXX. S'usa per agrupar proves que exerciten comportaments comuns. TestSuite: Agrupaci de proves que estan relacionades. TestRunner: Llenador de grups de proves. Es prov de la classe BaseTestRunner. TestCase+ Test Suite + BaseTestRunner = TestResult 12 13. Interfcies i classes de JUnit Assert: Cont mtodes que no fan res si la comprovaci s exitosa, i llencen una excepci quan falla. TestResult: Recolecta els errors i fallides que es produeixen a l'executar les proves. Test: Un test es pot executar i rep un TestResult. TestListener: Rep notificacions dels events que succeeixen durant una prova (p.e. la prova comena o acaba, s'ha produt un error, etc.) 13 14. Interfcies i classes de JUnit (2) TestCase: Defineix un entorn (o fixture) que pot usar-se per executar mltiples tests. TestSuite: executa una collecci de tests, que poden incloure tamb altres TestSuites. BaseTestRunner: superclasse de tots els llenadors de tests.14 15. La interfcie Test La interfcie que implementen tant la classe TestCase com la TestSuite s'anomena Test i cont el segent: package junit.framework;public interface Test {public abstract int countTestCases();public abstract void run(TestResult result);}15 16. Diagrama de classes 16 17. Creant una TestSuite Una TestSuite serveix per a que un TestRunner executi conjuntament diversos Tests relacionats Per no es vol complicar l'execuci de TestCases individualment Soluci: TestRunner crea una TestSuite de forma automtica a partir d'un TestCase (Ms endavant veurem que Test, TestSuite i TestCase sn un exemple de patr Composite)17 18. La TestSuite automtica Escaneja la classe de test per mtodes que comencin per test Crea una instncia de TestCase per a cadascun d'aquests mtodes El nom del mtode s passat al constructor per identificar cada instncia Aquest constructor amb nom era obligatori abans de JUnit 3.8. Ara noms cal si usat explcitament. La TestSuite es crea dins del mtode pblic i esttic suite()18 19. suite() per TestCalculator El mtode estatic que es crearia s equivalent a:public static Test suite() {return new TestSuite(TestCalculator.class);} Que s equivalent a:public static Test suite() {TestSuite suite = new TestSuite();suite.addTest(new TestCalculator(testAdd));return suite;}19 20. La tpica classe TestAllimport junit.framework.Test; import junit.framework.TestSuite; public class TestAll { public static Test suite() { TestSuite suite = new TestSuite(Tots els tests); suite.addTestSuite(TestCalculator.class); suite.addTestSuite(TestGenerator.suite()); return suite; } }20 21. Recollint resultats amb TestResult Una instncia de TestResult recull informaci sobre si els tests sn exitosos o fallen. P.e. si la lnia assertEquals(60, result, 0) falla, es crea una instncia de TestFailure i es guarda a TestResult TestRunner usa TestResult per informar de com ha anat l'execuci dels tests: si no hi ha cap TestFailure a TestResult, green bar si n'hi ha, s'indica el nombre d'errors i es mostra un volcat de la traa de la pila 21 22. Fallides i Errors JUnit distingeix entre: fallida: es 'normal' que es produeixin per exemple degut a canvis en el codi. error: condici no esperada per un test i que no s'hauria de produir mai. Quan es produeix una fallida: s'arregla el codi per arreglar la situaci Quan es produeix un error: comprovar l'entorn (configuraci, xarxa, bbdd, ...) comprovar el test comprovar el codi 22 23. Fallida 23 24. Error 24 25. Observant execuci amb TestListener La interfcie TestListener permet definir objectes que accedeixin al TestResult per a informar sobre el resultat d'un test. Per exemple, els diferents TestRunners implementen aquesta interfcie Es poden enregistrar tants TestsListeners com es vulgui per a fer el que es necessiti amb el TestResult.25 26. Interfcie TestListener public interface TestListener {// Cridat per notificar que s'ha produt un error void addError(Test test, Throwable t);// Cridat per notificar que s'ha produt una fallida void addFailure(Test test, AssertionFailedError e);// Cridat per notificar la fi d'execuci d'un test void endTest(Test test);// Cridat per notificar l'inici d'execuci d'un test void startTest(Test test); }26 27. Treballant amb TestCase Recordem que TestRunner executa una TestSuite que cont un o ms TestCases (o d'altres TestSuites) El framework cont varis TestRunners El framework crea una TestSuite per defecte Per tant, la nica classe que s absolutament necessari programar s TestCase27 28. Manegant recursos dins d'un TestCase Alguns tests requereixen recursos per funcionar (p.e. una connexi amb la BBDD) Varis tests d'un mateix TestCase poden necessitar aquests mateixos recursos Replicar el codi de creaci i configuraci d'aquests recursos en cada test no t sentit Fixture (accessori): el conjunt de recursos (o dades) comuns que es necessiten per executar un o ms tests.28 29. Execuci dels mtodes testXXX Una fixture s creada i destruda pels mtodes setUp i tearDown de TestCase. El TestCase crida de forma automtica setUp (tearDown) abans (desprs) d'executar cada mtode de test. Una de les raons de posar varis mtodes de test a un TestCase s compartir la fixture. 29 30. El supertipus Assert Classe d'utilitat que cont mtodes per avaluar condicions Tots ells llencen AssertionFailedError quan fallen i tenen vries versions (p.e. AssertEquals en t 20) Mirant el javadoc un veuen 38 mtodes per en el fons noms sn 8 mtodes: assertTrueassertNull assertFalse assertSame assertEqualsassertNotSame assertNotNull fail30 31. Els altres mtodes de TestCase public abstract class TestCase extends Assert implements Test { public TestCase() {...}public TestCase(String name) {...}public int countTestCases() {...}protected TestResult createTestResult() {...}public TestResult run() {...}public void run(TestResult result) {...}public void runBare() throws Throwable {...}protected void runTest() throws Throwable {...}protected void setUp() throws Exception {...}protected void tearDown() throws Exception {...}public String toString() {...}public String getName() {...}public String setName(String name) {...} } 31 32. Regla d'or de l'escriptura de tests Cada test unitari ha d'executar-se de manera independent de tots els altres tests unitaris han de poder executar-se en qualsevol ordre sense dependre d'efectes laterals produts pels tests previs Problem