Anotações
Apresentação de slides
Estrutura de tópicos
1
Modulo II
JUNIT
  • Prof. Ismael H F Santos


2
Bibliografia
  • JUnit in Action
3
Agenda:
  • JUNIT 3.8
  • JUNIT 4
4
MA-JUNIT
5
Teste Unitário
  • Imagine se um avião só fosse testado após a conclusão de sua construção....
6
Teste Unitário
  • O que é ?
    • O teste unitário é uma modalidade de testes que se concentra na verificação da menor unidade do projeto de software. É realizado o teste de uma unidade lógica, com uso de dados suficientes para se testar apenas a lógica da unidade em questão.


    • Em sistemas construídos com uso de linguagens orientadas a objetos, essa unidade pode ser identificada como um método, uma classe ou mesmo um objeto.
7
Teste Unitário
  • Por que ?
    • Previne contra o aparecimento de “BUG’S” oriundos de códigos mal escritos.
    • Código testado é mais confiável.
    • Permite alterações sem medo(coragem)
    • Testa situações de sucesso e de falha.
    • Resulta em outras práticas XP como : Código coletivo, refatoração, integração contínua.
    • Serve como métrica do projeto ( teste ==requisitos)
    • Gera e preserva um “conhecimento” sobre o projeto.
8
Teste Unitário
9
Teste Unitário
  • Quando fazer?


    • No início - TDD
    • Primeiro projetar e escrever as classes de testes, depois as classes com regra de negócios


    • Diariamente
    • È SUGERIDO que seja rodado os testes várias vezes ao dia (é fácil corrigir pequenos problemas do que corrigir um “problemão” somente no final do projeto.
10
Teste Unitário
  • Quem faz?
    • Test Case(para cada classe)
    • Desenvolvedor(Projeta, escreve e roda)


    • Test Suite(Rodas vários test cases)
    • Coordenador e Desenvolvedor  (Projeta, escreve e roda)


    • * Teste de aceitação(homologação) é feito junto ao cliente.

11
Teste Unitário
  • O Que Testar?
    • A principal regra para saber o que testar é: “Tenha criatividade para imaginar as possibilidades de testes”.
    • Comece pelas mais simples e deixe os testes “complexos“ para o final.
    • Use apenas dados suficientes (não teste 10 condições se três forem suficientes)
    • Não teste métodos triviais, tipo get e set.
    • No caso de um método set, só faça o teste caso haja validação de dados.
    • Achou um bug? Não conserte sem antes escrever um teste que o pegue (se você não o fizer, ele volta)
12
MA-JUNIT
13
JUnit
  • A unit test framework for Java
    • Authors:  Erich Gamma, Kent Beck


  • Objective:
    • “If tests are simple to create and execute, then programmers will be more inclined to create and execute tests.”


14
JUnit – O que é?
15
Para que serve?
16
Introduction
  • What do we need to do automated testing?
    • Test script
      • Actions to send to system under test (SUT).
      • Responses expected from SUT.
      • How to determine whether a test was successful or not?
    • Test execution system
      • Mechanism to read test scripts, and connect test case to SUT.
      • Keeps track of test results.


17
Test case verdicts
  • A verdict is the declared result of executing a single test.
  • Pass:  the test case achieved its intended purpose, and the software under test performed as expected.
  • Fail:  the test case achieved its intended purpose, but the software under test did not perform as expected.
  • Error:  the test case did not achieve its intended purpose.
    • Potential reasons:
      • An unexpected event occurred during the test case.
      • The test case could not be set up properly


18
A note on JUnit versions...
  • The version is 4.4, available from 2008
    • To use JUnit 4.x, you must use Java version 5 or 6
  • JUnit 4, introduced April 2006, is a significant (i.e. not compatible) change from prior versions.
  • JUnit 4 is used in this presentation.
  • Much of the JUnit documentation and examples currently available are for JUnit 3, which is slightly different.
    • JUnit 3 can be used with earlier versions of Java (such as 1.4.2).
    • The junit.org web site shows JUnit version 4 unless you ask for the old version.
    • Eclipse (3.2) gives the option of using JUnit 3.8 or JUnit 4.1, which are both packaged within Eclipse.
19
What is a JUnit Test?
  • A test “script” is just a collection of Java methods.
    • General idea is to create a few Java objects, do something interesting with them, and then determine if the objects have the correct properties.
  • What is added?  Assertions.
    • A package of methods that checks for various properties:
      • “equality” of objects
      • identical object references
      • null / non-null object references
    • The assertions are used to determine the test case verdict.
20
When is JUnit appropriate?
  • As the name implies…
    • for unit testing of small amounts of code
  • On its own, it is not intended for complex testing, system testing, etc.
  • In the test-driven development methodology, a JUnit test should be written first (before any code), and executed.
    • Then, implementation code should be written that would be the minimum code required to get the test to pass – and no extra functionality.
    • Once the code is written, re-execute the test and it should pass.
    • Every time new code is added, re-execute all tests again to be sure nothing gets broken.
21
JUnit- Arquitetura das Classes
22
Como usar o JUnit?
  • Há várias formas de usar o JUnit. Depende da metodologia de testes que está sendo usada
    • Código existente:
      • precisa-se escrever testes para classes que já foram implementadas
    • Desenvolvimento guiado por testes (TDD):
      • código novo só é escrito se houver um teste sem funcionar
    •  Onde obter?
      •  www.junit.org
    • Como instalar?
      • Incluir o arquivo junit.jar no classpath para compilar e rodar os programas de teste
23
MA-JUNIT
24
JUnit para testar código existente
25
JUnit 3.8 – Como implementar
26
JUnit 3.8 – Como implementar
  • 1. Crie uma classe que estenda junit.framework.TestCase
  • para cada classe a ser testada
  • import junit.framework.*;
  • class SuaClasseTest extends TestCase
  • {...
  • }
  • 2. Para cada método a ser testado defina um método public void test???() no test case
    • SuaClasse:
  • public int Soma(Object o ...)
  • { ...
  • }
    • SuaClasseTest:
  • public void testSoma()



27
JUnit 3.8 – Funcionamento
  • O TestRunner recebe uma subclasse de junit.framework.TestCase
    • Usa reflection (Cap 14) para achar métodos
  • Cada método testXXX(), executa:
    • 1. o método setUp()  /* Opcional */
    • 2. o próprio método testXXX()
    • 3. o método tearDown() /* Opcional */
  • O test case é instanciado para executar um método testXXX() de cada vez.
    • As alterações que ele fizer ao estado do objeto não afetarão os demais testes
  • Método pode terminar, falhar ou provocar exceção
28
JUnit – Analisando o Resultado
  • Em modo gráfico, os  métodos testados podem apresentar o seguintes resultados:


  • Sucesso


  • Falha


  • exceção


29
Exemplo: um test case
30
Exemplo: uma classe que faz o teste passar
31
Exemplo: Outra classe que faz o teste passar
32
Exemplo: como executar
33
TestSuite
34
Fixtures
35
Teste situações de falha
36
JUnit vs. asserções
37
Limitações do JUnit
38
"Usando Eclipse ......."


  • Usando Eclipse .......
39
Criando a classe de teste no Eclipse
40
 
41
 
42
 
43
 
44
 
45
 
46
 
47
 
48
 
49
 
50
 
51
 
52
 
53
 
54
JUnit 3.8 - Outros Métodos
de Testes
  •  assertEquals
    • Testa igualdade entre dois objetos(esperado x retornado)
  • assertFalse( )
    • Testa Retorno booleano  FALSO
  • assertTrue( )
    • Testa Retorno booleano  VERDADEIRO
  • assertNotNull( )
    • Testa se um valor de um objeto NÃO está NULO
  • assertNull( )
    • Testa se um valor de um objeto está NULO
55
JUnit 3.8 – métodos setUp() e tearDown()
  • São os dados reutilizados por vários testes, Inicializados no setUp() e destruídos no tearDown() (se necessário)


56
Técnicas complementares
  • É importante também, ser aplicado tipos de testes como:
    • Teste de Performance,
    • Teste de Carga,
    • Teste de estresse,
    • Teste de aceitação, etc.

57
MA-JUNIT
58
A JUnit 4 Test Case
  •  /** Test of setName() method, of class Value  */


  •  @Test
  •  public void createAndSetName()
  •  {
  •         Value v1 = new Value( );


  •         v1.setName( "Y" );


  •         String expected = "Y";
  •         String actual = v1.getName( );


  •         Assert.assertEquals( expected, actual );
  •  }
59
A JUnit 4 Test Case
  •  /** Test of setName() method, of class Value  */



  •  @Test


  •  public void createAndSetName()
  •  {
  •         Value v1 = new Value( );


  •         v1.setName( "Y" );


  •         String expected = "Y";
  •         String actual = v1.getName( );


  •         Assert.assertEquals( expected, actual );
  •  }
60
A JUnit 4 Test Case
  •  /** Test of setName() method, of class Value  */


  •  @Test
  •  public void createAndSetName()
  •  {
  •         Value v1 = new Value();


  •         v1.setName( "Y" );


  •         String expected = "Y";
  •         String actual = v1.getName();


  •         Assert.assertEquals( expected, actual );
  •  }
61
A JUnit 4 Test Case
  •  /** Test of setName() method, of class Value  */


  •  @Test
  •  public void createAndSetName()
  •  {
  •         Value v1 = new Value();


  •         v1.setName( "Y" );


  •         String expected = "Y"
  •         String actual = v1.getName( );


  •         Assert.assertEquals( expected, actual );
  •  }
62
A JUnit 4 Test Case
  •  /** Test of setName() method, of class Value  */


  •  @Test
  •  public void createAndSetName()
  •  {
  •         Value v1 = new Value( );


  •         v1.setName( "Y" );


  •         String expected = "Y";
  •         String actual = v1.getName( );


  •         Assert.assertEquals( expected, actual );
  •  }
63
Assertions
  • Assertions are defined in the JUnit class Assert
    • If an assertion is true, the method continues executing.
    • If any assertion is false, the method stops executing at that point, and the result for the test case will be fail.
    • If any other exception is thrown during the method, the result for the test case will be error.
    • If no assertions were violated for the entire method, the test case will pass.
  • All assertion methods are static methods
64
Assertion methods (1)
  • Boolean conditions are true or false
    • assertTrue(condition)
    • assertFalse(condition)
  • Objects are null or non-null
    • assertNull(object)
    • assertNotNull(object)
  • Objects are identical (i.e. two references to the same object), or not identical.
    • assertSame(expected, actual)
      • true if: expected == actual
    • assertNotSame(expected, actual)
65
Assertion methods (2)
  • “Equality” of objects:
    • assertEquals(expected, actual)
      • valid if: expected.equals( actual )
  • “Equality” of arrays:
    • assertArrayEquals(expected, actual)
      • arrays must have same length
      • for each valid value for i, check as appropriate:
        • assertEquals(expected[i],actual[i])
          • or
        • assertArrayEquals(expected[i],actual[i])
  • There is also an unconditional failure assertion fail() that always results in a fail verdict.
66
Assertion method parameters
  • In any assertion method with two parameters, the first parameter is the expected value, and the second parameter should be the actual value.
    • This does not affect the comparison, but this ordering is assumed for creating the failure message to the user.
  • Any assertion method can have an additional String parameter as the first parameter.  The string will be included in the failure message if the assertion fails.
    • Examples:
      • fail( message )
      • assertEquals( message, expected, actual)
67
Equality assertions
  • assertEquals(a,b) relies on the equals() method of the class under test.
    • The effect is to evaluate a.equals( b ).
    • It is up to the class under test to determine a suitable equality relation.  JUnit uses whatever is available.
    • Any class under test that does not override the equals() method from class Object will get the default equals() behaviour – that is, object identity.
  • If a and b are of a primitive type such as int, boolean, etc., then the following is done for assertEquals(a,b) :
    • a and b are converted to their equivalent object type (Integer, Boolean, etc.), and then a.equals( b ) is evaluated.

68
New assertions
  • JUnit 4 adds two assert() methods for comparing arrays.


  • These methods compare arrays in the most obvious way: Two arrays are equal if they have the same length and each element is equal to the corresponding element in the other array; otherwise, they're not. The case of one or both arrays being null is also handled.
    • public static void
    • assertEquals(Object[] expected, Object[] actual);


    • public static void
    • assertEquals(String message, Object[] expected,
    •                              Object[] actual);
69
Floating point assertions
  • When comparing floating point types (double or float), there is an additional required parameter delta.
  • The assertion evaluates
  • Math.abs( expected – actual ) <= delta
  • to avoid problems with round-off errors with floating point comparisons.
  • Example:
    • assertEquals( aDouble, anotherDouble, 0.0001 )
70
Organization of JUnit tests
  • Each method represents a single test case that can independently have a verdict (pass, error, fail).
  • Normally, all the tests for one Java class are grouped together into a separate class.
    • Naming convention:
      • Class to be tested:  Value
      • Class containing tests:  ValueTest
71
Running JUnit Tests (1)
  • The JUnit framework does not provide a graphical test runner.  Instead, it provides an API that can be used by IDEs to run test cases and a textual runner than can be used from a command line.


  • Eclipse and Netbeans each provide a graphical test runner that is integrated into their respective environments.
72
Running JUnit tests (2)
  • With the runner provided by JUnit:
    • When a class is selected for execution, all the test case methods in the class will be run.
    • The order in which the methods in the class are called (i.e. the order of test case execution) is
      not predictable.
  • Test runners provided by IDEs may allow the user to select particular methods, or to set the order of execution.
  • It is good practice to write tests with are independent of execution order, and that are without dependencies on the state any previous test(s).


73
Test fixtures
  • A test fixture is the context in which a test case runs.
  • Typically, test fixtures include:
    • Objects or resources that are available for use by any test case.
    • Activities required to make these objects available and/or resource allocation and de-allocation:  “setup” and “teardown”.



74
Setup and Teardown
  • For a collection of tests for a particular class, there are often some repeated tasks that must be done prior to each test case.
    • Examples:  create some “interesting” objects to work with, open a network connection, etc.
  • Likewise, at the end of each test case, there may be repeated tasks to clean up after test execution.
    • Ensures resources are released, test system is in known state for next test case, etc.
    • Since a test case failure ends execution of a test method at that point, code to clean up cannot be at the end of the method.
75
Setup and Teardown
  • Setup:
    • Use the @Before annotation on a method containing code to run before each test case.
  • Teardown (regardless of the verdict):
    • Use the @After annotation on a method containing code to run after each test case.
    • These methods will run even if exceptions are thrown in the test case or an assertion fails.
  • It is allowed to have any number of these annotations.
    • All methods annotated with @Before will be run before each test case, but they may be run in any order.
76
Example:  Using a file as a text fixture
  • public class OutputTest
  • {
  •     private File output;


  •     @Before public void createOutputFile() {
  •        output = new File(...);
  •     }
  •     @After public void deleteOutputFile() {
  •         output.delete();
  •     }
  •     @Test public void test1WithFile() {
  •        // code for test case objective
  •     }


  • @Test public void test2WithFile() {
  •        // code for test case objective
  •     }
  • }
77
Method execution order
  • createOutputFile()
  • test1WithFile()
  • deleteOutputFile()
  • createOutputFile()
  • test2WithFile()
  • deleteOutputFile()
  •      Assumption: test1WithFile runs before test2WithFile– which is not guaranteed.
78
Once-only setup
  • It is also possible to run a method once only for the entire test class, before any of the tests are executed, and prior to any @Before method(s).
  • Useful for starting servers, opening communications, etc. that are time-consuming to close and re-open for each test.
  • Indicate with @BeforeClass annotation (can only be used on one method, which must be static):
  •    @BeforeClass public static void anyNameHere() {
    •     // class setup code here
    • }
79
Once-only tear down
  • A corresponding once-only cleanup method is also available. It is run after all test case methods in the class have been executed, and after any @After methods
  • Useful for stopping servers, closing communication links, etc.
  • Indicate with @AfterClass annotation (can only be used on one method, which must be static):
  •    @AfterClass public static void anyNameHere(){
    •     // class cleanup code here
    • }
80
Example
  • // This class tests a lot of error conditions, which
  • // Xalan annoyingly logs to System.err.This hides System.err
  • // before each test and restores it after each test.


  • private PrintStream systemErr;


  • @BeforeClass protected void redirectStderr() {
  •   systemErr = System.err; // Hold on to the original value
  •   System.setErr(new PrintStream(new ByteArrayOutputStream()));
  • }


  • @AfterClass protected void tearDown() {
  •   // restore the original value
  •   System.setErr(systemErr);
  • }


81
Exception testing (1)
  • Add parameter to @Test annotation, indicating that a particular class of exception is expected to occur during the test.


    • @Test(expected=ExceptedTypeOfException.class)
    • public void testException()
    • {
    •    exceptionCausingMethod();
    • }
  • If no exception is thrown, or an unexpected exception occurs, the test will fail.
    • That is, reaching the end of the method with no exception will cause a test case failure.
  • Testing contents of the exception message, or limiting the scope of where the exception is expected requires using the approach on the next slide.
82
Exception testing in JUNIT 3.8
  • Catch exception, and use fail( ) if not thrown


    • public void testException()
    • {
    •    try
    •    {
    •       exceptionCausingMethod();


    •       // If this point is reached, the expected
    •       // exception was not thrown.
    •       fail("Exception should have occurred");
    •    }
    •    catch ( ExceptedTypeOfException exc )
    •    {
    •       String expected = "A suitable error message";
    •       String actual = exc.getMessage();
    •       Assert.assertEquals( expected, actual );
    •    }
    • }
83
Ignoring a test
  • The @Ignore annotation tells the runner to ignore the test and report that it was not run. You can pass in a string as a parameter to @Ignore annotation that explains why the test was ignored.
  • E.g. The new JUnit will not run a test method annotated with @Ignore(“Database is down”) but will only report it.


  •   // Java doesn't yet support the UTF-32BE and UTF32LE encodings
    • @Ignore(“Java doesn't yet support the UTF-32BE”)
    • @Test public void testUTF32BE()
    • throws ParsingException, IOException, XIncludeException {
    •   File input = new File("data/xinclude/input/UTF32BE.xml");
    •   Document doc = builder.build(input);
    •   Document result = XIncluder.resolve(doc);
    •   Document expectedResult = builder.build(
    •                new File(outputDir, "UTF32BE.xml"));
    •   assertEquals(expectedResult, result);
    • }
84
Timing out a test
  • You can pass in a timeout parameter to the test annotation to specify the timeout period in milliseconds. If the test takes more, it fails.


  • E.g. A method annotated with @Test (timeout=10) fails if it takes more than 10 milliseconds.


    • @Test(timeout=500)
    • public void retrieveAllElementsInDocument() {
    •      doc.query("//*");
    • }


85
Compatibility between JUNIT3.8 e 4
  • JUnit4Adapter enables compatibility with the old runners so that the new JUnit 4 tests can be run with the old runners. The suite method in the diagram above illustrates the use of JUnit4Adapter.



86
Running JUnit4 tests with JUnit3.8 runner
  • Use a normal class and not extend from junit.framework.TestCase.
  • Use the Test annotation to mark a method as a test method. To use the Test annotation import org.junit.Test
  • Run the test using JUnit4TestAdapter. If you want to learn more about JUnit4TestAdapter, keep reading ahead.
  • Alternatively, you can use the JUnitCore class in the org.junit.runner package. JUnit 4 runner can also run tests written using the old JUnit. To run the tests using the JUnitCore class via the command line, type:
  • java org.junit.runner.JUnitCore LibraryTest
87
Running JUnit4 tests with JUnit3.8 runner
88
Exercícios:
  • A classe Valores é capaz de armazenar até 10 valores inteiros positivos (v > 0). Esta classe deve implementar a seguinte interface
  • interface ValoresITF{
  • boolean ins(int v);//insere um valor
  • int del(int i);    // remove/retorna valor indice i
  • int size();        // retorna qtdade valores armazenados
  •   double mean();     // retorna média valores armazenados
  • int greater();     // retorna maior valor armazenado
  • int lower();       //retorna o menor valor armazenado
  • }
    • O método ins retorna true se o valor pode ser inserido
    • Os método del retorna o valor removido ou -1 se a lista está vazia
    • O método mean retorna 0 se a lista está vazia
    • Os métodos greater e lower retornam -1 se a lista está vazia


  • Determine um conjunto de casos de teste para esta classe.
  • Defina uma classe de teste para a classe Valores.
  • Implemente a classe Valores.
  • Verifique a cobertura dos testes incrementando-os para garantir cobertura de condição quando for o caso.
  • Execute os testes e verifique os resultados.
89
Solução
  • import junit.framework.TestCase;


  • public class testValores extends TestCase {
  •     private Valores val;
  • protected void setUp() throws Exception {
  • super.setUp();
  • val = new Valores();
  • val.ins(5);
  • val.ins(12);
  • val.ins(1);
  • val.ins(30);
  • val.ins(152);
  • val.ins(6);
  • }
  • public void testIns() {
  • assertEquals(false,val.ins(-10));
  • assertEquals(false,val.ins(0));
  • val.ins(2);
  • assertEquals(7,val.size());
  • val.ins(3);
  • assertEquals(8,val.size());
  • val.ins(4);
  • assertEquals(9,val.size());
  • val.ins(5);
  • assertEquals(10,val.size());
  • assertEquals(false,val.ins(11));
  • }


  • public void testDel() {
  • assertEquals(5,val.del(0));
  • assertEquals(6,val.del(4));
  • assertEquals(-1,val.del(4));
  • assertEquals(1,val.del(1));
  • assertEquals(12,val.del(0));
  • assertEquals(30,val.del(0));
  • assertEquals(152,val.del(0));
  • assertEquals(-1,val.del(0));
  • }
  • public void testMean() {
  • assertTrue(Math.round(34.3) == Math.round(val.mean()));
  • assertTrue(Math.round(0.0) == Math.round((new Valores()).mean()));
  • }
  • public void testGreater() {
  • assertEquals(152,val.greater());
  • assertEquals(-1,(new Valores()).greater());
  • }


  • public void testLower() {
  • assertEquals(1,val.lower());
  • assertEquals(-1,(new Valores()).lower());
  • }


  • }