   Experiência em missão crítica de missão crítica   Pioneira no ensino de Linux à distância   Parceira de treinamento ...
Testes em aplicações JEE:Montando sua infra de testes automatizados
Agenda●   Porque testar?●   Escrevendo testes com mais valor●   Problemas testando componentes JEE●    Como integrar conta...
Porque automatizar testes?●   Modinha...●   Eficiência dos testes de regressão    ●   Você pode melhorar/refatorar o siste...
Problemas na hora de testar?●    Mas te ensinaram como usar em situações do cotidiano?●    Até que ponto testar com objeto...
Problemas em testes decomponentes JEE●   Ciclo chato de desenvolvimentoImplementação          Deploy           Test    Imp...
Ciclo chato de desenvolvimentoMas eu utilizo Ant e o Maven para executaros testes pra mim, moleza!  www.4linux.com.br     ...
Utilizando ferramentas de    build●   Ant, Maven:    ●   Vantagem:         – Fácil de executar testes: mvn test (unitários...
Vei, na boa! Minha aplicação nem usa EJB             www.4linux.com.br             10 / 44
Para recursos simples da Web●   Sua aplicação não usa EJB, JTA, JMS?●   Você não precisa testar em um servidor de aplicaçõ...
Embedded Jetty●   Container de servlets leve●   Possui uma API para configurar e iniciar    uma instância do container.   ...
API do Jetty    A API do Jetty permite que você especifique os módulos    que são importantes para você, no caso, em seus ...
Tomcat Embedded●   Mais fácil de iniciar que o Jetty por todos os módulos já    virem configurados para iniciar.// Configu...
API do Tomcat : Adicionando ConteúdoVocê pode associar um WAR do file system a um contextoutilizando o método addWebappser...
Mas os como eu forneço pacotes com      as classes para os containers dentro      dos meus testes?www.4linux.com.br       ...
JBoss ShrinkWrap●   Projeto que ajuda automatizar e personalizar a criação de    pacotes Java    ●   EAR, WAR, JAR ou tamb...
JBoss ShrinkWrap                       <repository><project>                   <id>jboss-public-repository-group</id>  ......
Usando o ShrinkWrap // Exportando WAR: WebArchive war = ShrinkWrap.create(WebArchive.class); war.addPackages(true, "fourli...
Usando ShrinkWrap + Maven    ●   As vezes seu projeto está dividido em submódulos e um        componente que está sendo te...
MAS MEU PROJETO POSSUI EJBs,COMO TESTO?www.4linux.com.br    21 / 44
Apache OpenEJB●   Container EJB●   Desde 1999●   Como pode ser utilizado nos testes?    ●   Diferencial: Leve e rápido    ...
Configurando OpenEJB comMaven●    É utilizado como uma simples dependência.    <project>         ...                      ...
Iniciando container    ●   O container pode ser iniciado dentro dos testes, seja a        cada teste ou em um setup para t...
Testando SessionBeans@Statelesspublic class ServicoPagamento {     public void cobrar(double valor, CartaoCreditoInfo ccIn...
Configurando Recursos @Stateless public class OrderProcessor {                        Configurando recursos como      @Res...
Ligando o teste no container●   Há momentos onde é mais pratico permitir que o teste    tenha acesso aos recursos através ...
Mais eu quero testar em um        servidor de aplicação            completo, inútil!www.4linux.com.br                  28 ...
Testando na real comJBoss Arquillian●   Facilmente extensível.●   Ajuda a diminui o esforço para fazer testes em qualquer ...
Arquillian + Maven                                       Novamente adicionar repositório Jboss:                           ...
Arquillian + MavenArquillian com Glassfish                                         Extensões para<dependency>             ...
JBoss Arquillian●   Do que o Arquillian precisa?    ●   Os testes devem funcionar com        @RunWith(Arquillian.class)   ...
Teste com CDI usandoArquillian@RunWith(Arquillian.class)public class GerenciadorReservasTest {     @Inject     private Ger...
Testando em Containers   Remotos<dependency>     <groupId>org.jboss.as</groupId>     <artifactId>jboss-as-arquillian-conta...
Arquillian como Cliente                                                      Teste OUT Container@RunWith(Arquillian.class)...
Misturando In e Out Container@RunWith(Arquillian.class)public class GerenciadorReservasTest {     @Inject     private Gere...
PLUS: Infinitest●   Customizando a IDE:    ●   Teste continuo com Infinitest         –   Ajuda a executar os testes dentro...
Filtrando testes no Infinitest●    O Infinitest permite que você filtre os testes que serão     executados continuamente.●...
Emma  www.4linux.com.br   39 / 44
Emma  www.4linux.com.br   40 / 44
Cobertura dos Testes           www.4linux.com.br   41 / 44
Cobertura dos Testes           www.4linux.com.br   42 / 44
Chegaremos a 100% ???➢ Nem tudo será testado  ➢ Ex: Gets e Setters!  ➢ Classes sem lógica de negócio /    domínio➢ O aumen...
O que acontece na realidade?➢   A maioria das empresas estabelece um patamar    mínimo aceitável:    ➢  Ex. 80% de cobertu...
Testes em aplicações JEE: Montando sua infra de testes automatizados
Upcoming SlideShare
Loading in …5
×

Testes em aplicações JEE: Montando sua infra de testes automatizados

2,305 views

Published on

A 4Linux foi uma das patrocinadoras do Just Java 2012 que ocorreu nos dias 18 e 19/05/2012. Além do patrocínio, a equipe 4Linux foi responsável pela apresentação da palestra: Testes em aplicações Java EE: Montando sua infra de testes automatizados.

Published in: Technology

Testes em aplicações JEE: Montando sua infra de testes automatizados

  1. 1.  Experiência em missão crítica de missão crítica Pioneira no ensino de Linux à distância Parceira de treinamento IBM Primeira com LPI no Brasil + de 30.000 alunos satisfeitos Reconhecimento internacional Inovação com Hackerteen e Boteconet www.4linux.com.br 2 / 44
  2. 2. Testes em aplicações JEE:Montando sua infra de testes automatizados
  3. 3. Agenda● Porque testar?● Escrevendo testes com mais valor● Problemas testando componentes JEE● Como integrar containers aos testes. www.4linux.com.br 4 / 44
  4. 4. Porque automatizar testes?● Modinha...● Eficiência dos testes de regressão ● Você pode melhorar/refatorar o sistema com tranquilidade, se estragar você sabe instantaneamente que estragou● Integração contínua pode te tirar do apuro ● Você tem uma espécie de auditoria “vigiando” o funcionamento do seu código, se falhar você saberá exatamente onde e porque falhou www.4linux.com.br 5 / 44
  5. 5. Problemas na hora de testar?● Mas te ensinaram como usar em situações do cotidiano?● Até que ponto testar com objetos fake e mocks? Segundo Bill Burke, mocks te dão uma falsa sensação de segurança, pois permitem distorcer os testes para que seu código passe.● Difícil montar ambientes onde os testes podem ser executados● O quanto de esforço é necessário para executar testes em ferramentas de build e IDEs ao mesmo tempo. www.4linux.com.br 6 / 44
  6. 6. Problemas em testes decomponentes JEE● Ciclo chato de desenvolvimentoImplementação Deploy Test Implementação● Isolar o que deve ser testado ● Para um componente ser testado, ele dependente de um outro componente ou um serviço oferecidos pelo container. ● Exemplos: – Filas de mensageria – Transacionalidade – Segurança – Data Sources www.4linux.com.br 7 / 44
  7. 7. Ciclo chato de desenvolvimentoMas eu utilizo Ant e o Maven para executaros testes pra mim, moleza! www.4linux.com.br 8 / 44
  8. 8. Utilizando ferramentas de build● Ant, Maven: ● Vantagem: – Fácil de executar testes: mvn test (unitários) / mvn verify (unitários e integração) – Fácil integração com servidor de integração contínua como Jenkins. ● Desvantagem: – Executa todos os testes de um vez. – (Maven) Os erros são somente mostrados nos relátorios gerados – (Maven) não integra as suas fases de teste com a IDE www.4linux.com.br 9 / 44
  9. 9. Vei, na boa! Minha aplicação nem usa EJB www.4linux.com.br 10 / 44
  10. 10. Para recursos simples da Web● Sua aplicação não usa EJB, JTA, JMS?● Você não precisa testar em um servidor de aplicações FULL.● Utilize só um container web, mais leve e mais fácil de configurar.● Opções como o Jetty, Tomcat. Ambos possuem versão embutidas, que pode ser adicionada aos testes.● Jetty é dividido em módulos e permite especificar quais deles seram iniciaram com os testes.● Possuem plugins para Maven.● Possuem APIs que podem ser usadas dentro dos testes. www.4linux.com.br 11 / 44
  11. 11. Embedded Jetty● Container de servlets leve● Possui uma API para configurar e iniciar uma instância do container. Server server = new Server(8080); Context root = new Context(server,"/agenda",Context.SESSIONS); root.addServlet(new ServletHolder(new ContatoServlet()), "contatos"); server.start(); www.4linux.com.br 12 / 44
  12. 12. API do Jetty A API do Jetty permite que você especifique os módulos que são importantes para você, no caso, em seus testes. private static WebAppContext gerandoContextoAplicacao() throws Exception { WebAppContext context = new WebAppContext(); context.setWar(new File(URI_DO_WAR).getAbsolutePath()); context.setContextPath(“/aplicacao-do-jjustjava/”); context.setConfigurations(new Configuration[] { new AnnotationConfiguration(), new JettyWebXmlConfiguration(), new WebInfConfiguration(), new WebXmlConfiguration(), new TagLibConfiguration(), new MetaInfConfiguration(), new PlusConfiguration(), new FragmentConfiguration(), new EnvConfiguration() }); return context; } @BeforeClass public static void inicializar() throws Exception {Mais dependências para utilizar JSPs: server = new Server(SERVER_PORT); ● ant-1.6.5.jar WebAppContext contexto = gerandoContextoAplicacao(); ● core-3.1.1.jar ● jsp-2.1.jar server.setHandler(contexto); ● jsp-api-2.1.jar server.start(); } www.4linux.com.br 13 / 44
  13. 13. Tomcat Embedded● Mais fácil de iniciar que o Jetty por todos os módulos já virem configurados para iniciar.// Configura container de servlet embutidoTomcat servidor = new Tomcat();// Aponta o diretorio temporario para que o container necessitaservidor.setBaseDir("target/temp");// Especifica a porta onde irá funcionar <dependency>servidor.setPort(8081); <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId>// Inicia servidor <version>7.0.27</version> <scope>test</scope>servidor.start(); </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <version>7.0.27</version> <scope>test</scope> </dependency> www.4linux.com.br 14 / 44
  14. 14. API do Tomcat : Adicionando ConteúdoVocê pode associar um WAR do file system a um contextoutilizando o método addWebappservidor.addWebapp("/carrinho", enderecoDoWar); Adiciona o WAR ao contexto /carrinhoTambém é possível tornar um diretório, o contexto da aplicação, adicionando servlets aoContainer e mapeando-os no contexto.File diretorioWebapp = new File("src/main/webapp");Context contexto = servidor.addWebapp("/", diretorioWebapp.getAbsolutePath());servidor.addServlet("/", "LeilaoServlet", new LeilaoServlet());contexto.addServletMapping("/leilao", "LeilaoServlet"); Mapeando o Servlet adicionado www.4linux.com.br 15 / 44
  15. 15. Mas os como eu forneço pacotes com as classes para os containers dentro dos meus testes?www.4linux.com.br 16 / 44
  16. 16. JBoss ShrinkWrap● Projeto que ajuda automatizar e personalizar a criação de pacotes Java ● EAR, WAR, JAR ou também qualquer outro Zip. ● A maioria dos container embutidos permitem especificar um pacote para registrado inserido em um contexto. WebArchive warAplicacao = ShrinkWrap.create(WebArchive.class, “livraria.war”) .addClasses(Cliente.class, CartaoCreditoInfo.class) .addPackage(“fourlinux.justjava.store.dao”); .setWebXML(“/src/test/resources/web.xml”); www.4linux.com.br 17 / 44
  17. 17. JBoss ShrinkWrap <repository><project> <id>jboss-public-repository-group</id> ... <name>JBoss Public Maven Repository Group</name> <dependencies> <url>https://repository.jboss.org/nexus/content/groups/public/</url> ... </repository> <dependency> <groupId>org.jboss.shrinkwrap</groupId> <artifactId>shrinkwrap-api</artifactId> </dependency> <dependency> <groupId>org.jboss.shrinkwrap</groupId> <artifactId>shrinkwrap-impl-base</artifactId> <scope>test</scope> </dependency>...</dependencies>...</project> www.4linux.com.br 18 / 44
  18. 18. Usando o ShrinkWrap // Exportando WAR: WebArchive war = ShrinkWrap.create(WebArchive.class); war.addPackages(true, "fourlinux.justjava"); Adiciona todas as classes do seguinte pacote recursivamente war.as(ZipExporter.class).exportTo(new File(“/target/shrinkwrap/aplicacao.war”)); Cria um arquivo zip para o conteúdo indicado // Embedded Jetty WebAppContext context = new WebAppContext(); context.setWar(new File(uriDoWar).getAbsolutePath());; www.4linux.com.br 19 / 44
  19. 19. Usando ShrinkWrap + Maven ● As vezes seu projeto está dividido em submódulos e um componente que está sendo testado depende de um módulo declarado no POM ● Ou você precisa adicionar um driver JDBC no pacote para testar ShrinkWrap ResolverMavenDependencyResolver resolver = DependencyResolvers.use( MavenDependencyResolver.class);MavenDependencyBuilder dominio = resolver.artifact("soujava.justjava:livraria-dominio:1.0");carrinho.addAsLibraries(dominio.resolveAs(GenericArchive.class)); www.4linux.com.br 20 / 44
  20. 20. MAS MEU PROJETO POSSUI EJBs,COMO TESTO?www.4linux.com.br 21 / 44
  21. 21. Apache OpenEJB● Container EJB● Desde 1999● Como pode ser utilizado nos testes? ● Diferencial: Leve e rápido ● Pode ser iniciado dentro dos testes. ● Suporta as versões 3.1, 3.0, 2.1, 2.0, 1.1 ● Simples configuração e inicialização. ● Simplicica os ciclos de desenvolvimento e teste. www.4linux.com.br 22 / 44
  22. 22. Configurando OpenEJB comMaven● É utilizado como uma simples dependência. <project> ... API <dependency> <groupId>org.apache.openejb</groupId> <artifactId>javaee-api</artifactId> <scope>provided</scope> <version>6.0-3-SNAPSHOT</version> </dependency> Container <dependency> <groupId>org.apache.openejb</groupId> <artifactId>openejb-core</artifactId> <scope>test</scope> <version>4.0.0-beta-1</version> </dependency> </project> Preciso de suporte a JPA, o que faço? <dependency> <groupId>org.apache.openejb</groupId> OpenEJB com Hibernate <artifactId>openejb-core-hibernate</artifactId> <version>4.0.0-beta-1</version> <type>pom</type> </dependency> www.4linux.com.br 23 / 44
  23. 23. Iniciando container ● O container pode ser iniciado dentro dos testes, seja a cada teste ou em um setup para todos os testes.@Before <= EJB 3.0public void inicializacao() { Properties props = new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory"); Context context = new InitialContext(props);} >= EJB 3.1@Beforepublic void inicializacao() { EjbContainer container = EjbContainer.createEjbContainer(); Context context = container.getContext();} www.4linux.com.br 24 / 44
  24. 24. Testando SessionBeans@Statelesspublic class ServicoPagamento { public void cobrar(double valor, CartaoCreditoInfo ccInfo) { ... }} Provê um JNDI padrão que você pode customizá-lo.@Testpublic class ServiceoPagamentoIT { @Test(expected=IllegalArgumentException.class) public void valorNegativoLancaExcecao() { Context contexto = EjbContainer.createEjbContainer().getContext(); ServicoPagamento sp = (ServicoPagamento) contexto.lookup(“java:global/projeto/ServicoPagamento”); sp.cobrar(-5, ccInfo); }} Utilizando o JNDI para recuperar componentes como session beansO OpenEJB caça sua aplicação por componentes JavaEE que podem ser de sua responsabilidade. www.4linux.com.br 25 / 44
  25. 25. Configurando Recursos @Stateless public class OrderProcessor { Configurando recursos como @Resource DataSource, filas, tópicos, DataSource dataSource; fábricas de conexões... ... } public class OrderProcessorIT { @Test public void processOrderAddItensToDatabase() { Properties props = new Properties(); props.put("shopDatabase", "new://Resource?type=DataSource"); props.put("shopDatabase.JdbcDriver", "org.hsqldb.jdbcDriver"); props.put("shopDatabase.JdbcUrl", "jdbc:hsqldb:mem:shopdb"); Context contexto = EjbContainer.createEjbContainer(props).getContext(); OrderProcessor orders = (OrderProcessor) contexto.lookup(“java:global/projeto/OrderProcessor”); } } www.4linux.com.br 26 / 44
  26. 26. Ligando o teste no container● Há momentos onde é mais pratico permitir que o teste tenha acesso aos recursos através de injeção de dependência. public class GameContextIT { @PersistenceContext(unitName=”gameunit”) private EntityManager em; @Resource private Queue filaJogadores; Acesso a todos os recursos do Container, como filas, @EJB datasources, ejbs e ao GameController controller; contexto cdi … public SetUp() throws Exception { EJBContainer container = EJBContainer.createEJBContainer(); container.getContext().bind(“inject”, this); } } www.4linux.com.br 27 / 44
  27. 27. Mais eu quero testar em um servidor de aplicação completo, inútil!www.4linux.com.br 28 / 44
  28. 28. Testando na real comJBoss Arquillian● Facilmente extensível.● Ajuda a diminui o esforço para fazer testes em qualquer tipo de container, seja remoto ou embutido.● Gerencia todo o ciclo de vida do container e da aplicação sendo executada nele.● Com ajuda do ShrinkWrap, permite montar pacotes personalizados para deploy.● Permite executar testes dentro e fora do container. www.4linux.com.br 29 / 44
  29. 29. Arquillian + Maven Novamente adicionar repositório Jboss: http://repository.jboss.org/nexus/content/groups/public<dependency> <groupId>org.jboss.arquillian</groupId> <artifactId>arquillian-bom</artifactId> <version>1.0.0.Final</version> Importando dependências <scope>import</scope> do Arquillian <type>pom</type></dependency> Integração com Junit ou TestNG <dependency> <groupId>org.jboss.arquillian.junit</groupId> <artifactId>arquillian-junit-container</artifactId> <version>1.0.0.Final</version> </dependency> Falta a extensão do container... www.4linux.com.br 30 / 44
  30. 30. Arquillian + MavenArquillian com Glassfish Extensões para<dependency> ● JBoss <groupId>org.jboss.arquillian.container</groupId> ● Tomcat <artifactId>arquillian-glassfish-embedded-3.1</artifactId> ● Glassfish <version>1.0.0.CR3</version> ● Resin <scope>test</scope></dependency> Extensão para glassfish ● Weld ● OSGI<dependency> <groupId>org.glassfish.main.extras</groupId> ● CloudBees <artifactId>glassfish-embedded-all</artifactId> ● OpenEJB <version>3.1.2</version> ● Jetty <scope>test</scope> ● Google AppEngine</dependency> ● Spring Glassfish Embutido www.4linux.com.br 31 / 44
  31. 31. JBoss Arquillian● Do que o Arquillian precisa? ● Os testes devem funcionar com @RunWith(Arquillian.class) ● Pelo menos um método anotado com @Test ● Um método estático que entregue um pacote Java montado pelo ShrinkWrap ● Um container onde ele irá instalar o pacote. www.4linux.com.br 32 / 44
  32. 32. Teste com CDI usandoArquillian@RunWith(Arquillian.class)public class GerenciadorReservasTest { @Inject private GerenciadorReservas reservas; @Deployment public static JavaArchive gerandoArquivoDeploy() { JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class); arquivo.addPackages(true, “fourlinux.justjava”); arquivo.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); return arquivo; } @Test public void reservaDeveGerarCobranca() throws Exception { Cabine cabine = new Cabine(“Titanic”, “A12”, Tipo.LUXO, 340.00f); Usuario usuario = new Usuario("gabriel.ozeas1@gmail.com", "Gabriel Ozeas"); Cobranca cobranca = reservas.reservarCabine(new Cabine[]{cabine}, usuario); assertEquals(new Float(340), new Float(cobranca.getValor())); }} www.4linux.com.br 33 / 44
  33. 33. Testando em Containers Remotos<dependency> <groupId>org.jboss.as</groupId> <artifactId>jboss-as-arquillian-container-remote</artifactId> <version>7.1.1.Final</version> <scope>test</scope></dependency> Cliente JBoss Remoto<dependency> <groupId>org.jboss.as</groupId> <artifactId>jboss-as-controller-client</artifactId> <version>7.1.1.Final</version> <scope>test</scope></dependency> Utilizando containers remotos e gerenciados, faz com que eles iniciem em outra JVM, ou seja os logs e debug não estão disponiveis na JVM que iniciou os testes. www.4linux.com.br 34 / 44
  34. 34. Arquillian como Cliente Teste OUT Container@RunWith(Arquillian.class)public class GerenciadorReservasTest { Deploy no container, mas testa no cliente @Deployment(testable = false) public static JavaArchive gerandoArquivoDeploy() { JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class); arquivo.addPackages(true, “fourlinux.justjava”); arquivo.setWebXML(“src/main/webapp/WEB-INF/web.xml”); return arquivo; } Testando UI com Selenium @Test public void verificandoTotalItensInicial() throws Exception { WebDriver navegador = new HtmlUnitDriver(); navegador.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); navegador.get("http://localhost:8081/leilao"); WebElement body = navegador.findElement(By.tagName("h1")); assertEquals("Histórico do item", body.getText()); }} www.4linux.com.br 35 / 44
  35. 35. Misturando In e Out Container@RunWith(Arquillian.class)public class GerenciadorReservasTest { @Inject private GerenciadorReservas reservas; @Deployment public static JavaArchive gerandoArquivoDeploy() { JavaArchive arquivo = ShrinkWrap.create(JavaArchive.class); arquivo.addClasses(...); ... } Teste será executado na JVM do container @Test public void reservaDeveGerarCobranca() throws Exception { …. Cobranca cobranca = reservas.reservarCabine(new Cabine[]{cabine}, usuario); assertEquals(new Float(340), new Float(cobranca.getValor())); } @Test Teste será executado na JVM que inicou os testes @RunAsClient public void verificandoTotalItensInicial() throws Exception { WebDriver navegador = new HtmlUnitDriver(); navegador.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); ... } www.4linux.com.br 36 / 44
  36. 36. PLUS: Infinitest● Customizando a IDE: ● Teste continuo com Infinitest – Ajuda a executar os testes dentro do Eclipse automaticamente – Verde, passou, Vermelho Falhou. – Permite criar filtros para escolher quais testes serão sempre executados. – Recomendado para executar em testes de unidade, pois são normalmente executados em millisegundos. Testes que falharam www.4linux.com.br 37 / 44
  37. 37. Filtrando testes no Infinitest● O Infinitest permite que você filtre os testes que serão executados continuamente.● Arquivo infinitest.filtersBloqueia todos os testes de integração:.*ITestBloqueia todos os testes de um pacote:org.soujava.justjava..*Bloqueia todos os teste do projeto:.* www.4linux.com.br 38 / 44
  38. 38. Emma www.4linux.com.br 39 / 44
  39. 39. Emma www.4linux.com.br 40 / 44
  40. 40. Cobertura dos Testes www.4linux.com.br 41 / 44
  41. 41. Cobertura dos Testes www.4linux.com.br 42 / 44
  42. 42. Chegaremos a 100% ???➢ Nem tudo será testado ➢ Ex: Gets e Setters! ➢ Classes sem lógica de negócio / domínio➢ O aumento do esforço para se chegar a 100% pode não valer a pena! www.4linux.com.br 43 / 44
  43. 43. O que acontece na realidade?➢ A maioria das empresas estabelece um patamar mínimo aceitável: ➢ Ex. 80% de cobertura (somente um exemplo)!➢ Os testes unitários e a verificação de cobertura são feitos automaticamente; ➢ A verificação de cobertura pode ser configurada para analisar apenas algumas classes ou pacotes ➢ Utilizar patamares diferentes para recusar o build em cada classe ou pacote. www.4linux.com.br 44 / 44

×