Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Lidando com o Caos: Testando Código PL/SQL em um Projeto Critico

Lidando com o Caos: Testando Código PL/SQL em um Projeto Critico

Imagine entrar em um projeto critico de uma grande empresa onde todo o desenvolvimento se baseia em integrar diversos outros sistemas mais criticos ainda? Agora, imagine que essa integração ocorrerá toda via banco de dados através de stored procedures, de código PLSQL?

São milhares de linhas de código PLSQL executando toda lógica de negócio que deve rodar com alto desempenho e, principalmente, corretude. Uma simples falha e todo um sistema de Logística pode parar! Como garantir que tudo funciona de forma correta e mais, que tenhamos ao final um código manutenível? Nessa apresentação vamos expor como nossa equipe conseguiu implementar todo esse código PLSQL com qualidade e o melhor de tudo, coberto por centenas de testes automatizados; o uso de testes foi crucial para o sucesso! Some a isso todo o desafio cultural e desconfiança do mercado em testar código PLSQL, a falta de literatura sobre o assunto e a real necessidade de automatizar ao máximo o ambiente de desenvolvimento.

Essa palestra te fará repensar sobre como você programa em PLSQL.

Palestra ministrada no evento Javou #9 da JavaCE em MAR-2017 (http://www.javace.org/javou-09-casos-de-sucesso/) por Rafael Ponte e Eduardo Menezes ([email protected])

Rafael Ponte

March 04, 2017
Tweet

More Decks by Rafael Ponte

Other Decks in Technology

Transcript

  1. Olá, tudo bom? Meu nome Rafael. Novo desenvolvedor no projeto.

    Opa, sou Dudu. O líder técnico do projeto.
  2. Olá, tudo bom? Meu nome Rafael. Novo desenvolvedor no projeto.

    Opa, sou Dudu. O líder técnico do projeto. 300, viu?
  3. Olá, tudo bom? Meu nome Rafael. Novo desenvolvedor no projeto.

    Opa, sou Dudu. O líder técnico do projeto. 300, viu? ahn!!? 300? 300 o que?
  4. Olá, tudo bom? Meu nome Rafael. Novo desenvolvedor no projeto.

    Opa, sou Dudu. O líder técnico do projeto. 300, viu? ahn!!? 300? 300 o que? R$300.000 por hora se o sistema parar!
  5. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  6. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  7. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  8. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  9. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  10. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  11. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  12. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  13. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}”; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.VARCHAR); cs.setString(2, uf); cs.execute(); return cs.getDouble(1); } } Java
  14. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}”; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.VARCHAR); cs.setString(2, uf); cs.execute(); return cs.getDouble(1); } } Java
  15. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}”; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.VARCHAR); cs.setString(2, uf); cs.execute(); return cs.getDouble(1); } } Java
  16. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.VARCHAR); cs.setString(2, uf); cs.execute(); return cs.getDouble(1); } } Java
  17. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.VARCHAR); cs.setString(2, uf); cs.execute(); return cs.getDouble(1); } } Java
  18. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.DOUBLE); cs.setString(2, uf); cs.execute(); return cs.getDouble(1); } } Java
  19. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.DOUBLE); cs.setString(2, uf); cs.execute(); return cs.getDouble(1); } } Java
  20. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.DOUBLE); cs.setString(2, uf); cs.execute(); return cs.getDouble(1); } } Java
  21. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.DOUBLE); cs.setString(2, uf); cs.execute(); // executa function return cs.getDouble(1); } } Java
  22. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.DOUBLE); cs.setString(2, uf); cs.execute(); // executa function return cs.getDouble(1); } } Java
  23. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.DOUBLE); cs.setString(2, uf); cs.execute(); // executa function return cs.getDouble(1); } } Java
  24. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  25. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  26. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  27. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  28. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  29. jUnit class FreteServiceTest { @Test public void deveCalcularFrete() { //

    cenário String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } }
  30. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  31. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  32. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  33. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  34. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  35. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  36. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  37. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  38. -- Calcula Frete function calc_frete(uf varchar2)
 return number is begin

    if uf = 'SP' then return 30.0; end if; return 20.20; end; PL/SQL
  39. function calc_frete(uf varchar2) return number is valor_frete number; begin --

    busca valor do frete na tabela SELECT f.valor INTO valor_frete FROM TB_FRETE_VALOR f WHERE f.uf_destino = uf; return valor_frete; end; PL/SQL
  40. function calc_frete(uf varchar2) return number is valor_frete number; begin --

    busca valor do frete na tabela SELECT f.valor FROM TB_FRETE_VALOR f WHERE f.uf_destino = uf; return valor_frete; end; PL/SQL
  41. function calc_frete(uf varchar2) return number is valor_frete number; begin --

    busca valor do frete na tabela SELECT f.valor FROM TB_FRETE_VALOR f WHERE f.uf_destino = uf; return valor_frete; end; PL/SQL
  42. function calc_frete(uf varchar2) return number is valor_frete number; begin --

    busca valor do frete na tabela SELECT f.valor INTO valor_frete FROM TB_FRETE_VALOR f WHERE f.uf_destino = uf; return valor_frete; end; PL/SQL
  43. function calc_frete(uf varchar2) return number is valor_frete number; begin --

    busca valor do frete na tabela SELECT f.valor INTO valor_frete FROM TB_FRETE_VALOR f WHERE f.uf_destino = uf; return valor_frete; end; PL/SQL
  44. function calc_frete(uf varchar2) return number is valor_frete number; begin --

    busca valor do frete na tabela SELECT f.valor INTO valor_frete FROM TB_FRETE_VALOR f WHERE f.uf_destino = uf; return valor_frete; end; PL/SQL
  45. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.DOUBLE); cs.setString(2, uf); cs.execute(); // executa function return cs.getDouble(1); } } Java
  46. class FreteService { public Double calcula(String uf) { String sql

    = "{? = call calc_frete(?)}"; Connection c = // abre conexão CallableStatement cs = c.prepareCall(sql); cs.registerOutParameter(1, Types.DOUBLE); cs.setString(2, uf); cs.execute(); // executa function return cs.getDouble(1); } } Java Nada!
  47. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  48. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; this.limpaEInsereFrete("SP", 30.0); // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  49. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; this.limpaEInsereFrete("SP", 30.0); // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  50. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; this.limpaEInsereFrete("SP", 30.0); // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit DELETE FROM TB_FRETE_VALOR;
 INSERT INTO TB_FRETE_VALOR VALUES(1, ‘SP’, 30.30);
  51. class FreteServiceTest { @Test public void deveCalcularFrete() { // cenário

    String uf = "SP"; this.limpaEInsereFrete("SP", 30.0); // ação FreteService service = new FreteService(); double valor = service.calcula(uf); // validação assertEquals(30.0, valor); } } jUnit
  52. function calc_frete(uf varchar2) return number is valor_frete number; begin --

    busca valor do frete na tabela SELECT f.valor INTO valor_frete FROM TB_FRETE_VALOR f WHERE f.uf_destino = uf; return valor_frete; end; PL/SQL
  53. function calc_frete(uf varchar2) return number is valor_frete number; begin --

    busca valor do frete na tabela SELECT f.valor INTO valor_frete FROM TB_FRETE_VALOR f WHERE f.uf_destino = uf; return valor_frete; EXCEPTION WHEN no_data_found THEN raise_application_error(-20200, ‘oops!’); end; PL/SQL