Labs SD >
Para garantir a qualidade do código do Web Service, é necessário produzir testes que incidem sobre diferentes módulos e aspetos:
Vamos então analisar as ferramentas de teste utilizadas.
O JUnit é uma biblioteca Java para escrever testes ao código.
O Maven já vem preparado para executar testes unitários,
na fase test do ciclo de vida,
mas é necessário adicionar a dependência para a biblioteca JUnit:
... <!-- JUnit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
As classes de testes são aquelas cujo nome, por omissão, termina com Test. Devem ser arrumadas na pasta src/test/java do projeto.
Uma classe de testes tem a seguinte estrutura:
package example.test; import org.junit.*; import static org.junit.Assert.*; /** Test suite */ public class ExampleTest { // static members // one-time initialization and clean-up @BeforeClass public static void oneTimeSetUp() { } @AfterClass public static void oneTimeTearDown() { } // members // initialization and clean-up for each test @Before public void setUp() { } @After public void tearDown() { } // tests @Test public void test() { // assertEquals(expected, actual); // if the assert fails, the test fails } }
No JUnit 4 são utilizadas anotações para definir qual o papel dos métodos.
Os métodos anotados com @Test são testes individuais.
@Before e @After são executados antes e depois de cada teste.
@BeforeClass e @AfterClass são executados apenas uma vez para o conjunto de testes da classe.
As funções de assert permitem verificar o resultado do teste: assertEquals(expected, actual); expected é o valor esperado, actual é o valor que resultou da execução
O plug-in de Maven que corre os testes chama-se
Surefire.
Os exemplos seguintes mostram como correr os testes e
como controlar quais os testes a executar.
// to compile and execute all tests $ mvn test // to execute only a specific test class $ mvn test -Dtest=PingIT // to execute only a specific test $ mvn test -Dtest=PingIT#testPing // you can also use wildcards (the example below will match classes starting with P) $ mvn test -Dtest=P* // to skip integration tests $ mvn package -Dtest.skip=truePara mais informação sobre JUnit, consultar:
Os testes de integração (integration tests) verificam o comportamento de vários componentes do sistema.
Por outras palavras, verificam se os componentes se integram bem uns com os outros.
No contexto dos Web Services,
os testes de integração são um programa cliente que faz invocações remotas a um programa servidor,
verificando o contrato das operações remotas definidas no WSDL.
Assume-se que todos os Web Services já foram previamente lançados antes de correr os testes de integração.
O JUnit é também ser usado para fazer testes de integração.
O Maven executa os testes de integração na fase verify do ciclo de vida. É necessário configurar um plug-in da forma ilustrada abaixo:
... <plugin> <artifactId>maven-failsafe-plugin</artifactId> <version>2.19.1</version> <executions> <execution> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> </execution> </executions> </plugin>
Por convenção, as classes de testes de integração terminam com (IT). Devem ser também arrumadas na pasta src/test/java do projeto.
Uma vez que os testes de integração efetuam invocações remotas, necessitam de criar um Stub de invocação do serviço. O excerto de código abaixo mostra a criação de chamado port. Este objecto, dado que é um membro da classe, estará acessível em todos os métodos de teste.
... // static members private static CalcPortType client; // one-time initialization and clean-up @BeforeClass public static void oneTimeSetUp() { client = new CalcClient(uddiURL, wsName); } @AfterClass public static void oneTimeTearDown() { client = null; } ... @Test public void testPing) { final int result= client.sum(1, 2); assertEquals(3, result); } ...
No exemplo acima o endereço do serviço (endpoint address) é obtido de forma dinâmica a partir do UDDI, que se assume ser consultado pelo construtor do objeto cliente.
Os testes de integração terão que lidar com exceções dos Web Services, quer as geradas na aplicação, quer as geradas na comunicação.
Para implementar testes de exceções existem duas abordagens: com expected na anotação @Test ou não.
... @Test(expected=ExampleException.class) public void testExceptionWithAnnotation() throws Exception { // ... code that must throw an exception // JUnit expects the exception declared in the annotation // if it is not thrown, the test fails } ... @Test public void testExceptionWithoutAnnotation() throws Exception { try { // ... code that must throw an exception fail(); } catch (Exception e) { // expected // check message of exception etc } } ...
O JMockit é uma biblioteca Java para
gerar dinamicamente objetos mock para testes
(mock pode-se traduzir por fictício ou simulado).
Os objectos mock têm um comportamento pré-determinado e
substituem objectos reais que são muito "caros" de obter ou
configurar para determinadas situações.
Por exemplo,
os objectos mock podem ser usados para simular o servidor UDDI ou
para lançar erros de Web Services que são difíceis de causar na prática.
Para testar componentes individuais, fazer testes unitários (Test) com JUnit.
Para simular objectos remotos ou outras dependências externas em testes unitários, usar JMockit.
Para testar a integração de componentes, fazer testes de integração (IT) com JUnit. Dado o seu objetivo de verificar o comportamento do sistema como um todo, os testes de integração não devem usar objectos simulados.
O objetivo é construir testes para um dos serviços do Projeto.
Bons testes! :)
© Docentes de Sistemas Distribuídos,
Dep. Eng. Informática,
Técnico Lisboa