Forum Discussion

jdwather's avatar
jdwather
Contributor
7 years ago
Solved

How to pass to the next test in the script after an error occurs.

Hi
I performed my tests using two levels of test list, where in the first level has the procedure call containing all tests of a particular module and when executing an item in this list, inside this item has the list of tests that is executed, when an error occurs I made the handling of this error in the OnLogError to execute the next test of the list, but I just encountered a recursion error in the OnLogError, I would like to know if anyone would have any idea how I can call the next test of the my list when an error occurs, avoiding recursion. I used the deplhi script language.
Here's an example of how I run my lists:

 

 

UnitPrincipal:

 

// runs the first test list

procedure executaTestesListaPrimeiroNivel;
var lista, teste : string;
var i, posicao : integer;
begin
  posicao : = 0;
  if Project.Variables.IdAvancado > 0 then posicao :=  Project.Variables.IdAvancado;
  lista := Project.Variables.listaPrimeiroNivel;


  if posicao <= aqString.GetListLength(lista) - 2 then
  begin
    for i := posicao to aqString.GetListLength(lista) - 2 do
    begin
      teste := aqString.GetListItem(lista, i);
      Project.Variables.IdAvancado := i;
      Evaluate(''+teste+'');
      Log.Message('Executou o teste: '+teste);
    end;
  end;
  Project.Variables.IdAvancado := 0;
end;

 

 

procedure Geral_Modules;
begin
  removeVariavelProjeto('listaPrimeiroNivel');
  Project.Variables.descAvancadoGeral := 'Geral_Modules';
  adicionaTesteListaPrimeiroNivel('Module1');
  adicionaTesteListaPrimeiroNivel('Module2');
  adicionaTesteListaPrimeiroNivel('Module3');
  executaTestesListaPrimeiroNivel;
end;

 

 

 

 

Unit Module 1

// runs the second list of tests

procedure executaTestesListaSegundoNivel(descUnit : string);
var lista, teste : string;
var i, posicao : integer;
begin
  posicao : = 0;
  if Project.Variables.IdItem > 0 then posicao :=  Project.Variables.IdItem;
  lista := Project.Variables.listaSegundoNivel;
  // Adicionada verificação para quando ocorrer erro no ultimo item da lista continuar
  if posicao <= aqString.GetListLength(lista) - 2 then
  begin
    // foi adicionado -2 ao tamanho da lista porque o ao adiconar um novo item na lista o testComplete adiicona ";"(ponto e virgula) ao final assim criando um item vazio no final
    for i := posicao to aqString.GetListLength(lista) - 2 do
    begin
      teste := aqString.GetListItem(lista, i);
      Project.Variables.IdItem := i;
      removeVariavelProjeto('listaNomeRotina');
      Evaluate(''+descUnit+'.'+teste+'');
      Log.Message('Executou o teste: '+teste);
    end;
  end;
  Project.Variables.IdItem := 0;
end;

 

 

procedure teste1;
begin
  inserirItemBD('BAN002CA','001', 'CT_1_14', 'Cadastrar conta bancária para o banco Itaú');
  deletaIniTestes;
  configBaseIni('ECO');
  IniciaSistemaEco;
  BAN002CA_Avancado_Condicoes_Item_01;
  FBAN002CA_Test_01;
  fecharSistemaEco;
  copiaBaseIni('BAN002CA','ECO', '001');
end;

procedure teste2;
begin
  inserirItemBD('BAN002CA','002', 'CT_1_129', 'Cadastrar conta bancária para o banco Santander');
  deletaIniTestes;
  configBaseIni('ECO');
  IniciaSistemaEco;
  BAN002CA_Avancado_Condicoes_Item_02;
  FBAN002CA_Test_02;
  fecharSistemaEco;
  copiaBaseIni('BAN002CA','ECO', '002');
end;

procedure teste3;
begin
  inserirItemBD('BAN002CA','003', 'CT_1_136', 'Cadastrar conta bancária para o banco Bradesco');
  deletaIniTestes;
  configBaseIni('ECO');
  IniciaSistemaEco;
  BAN002CA_Avancado_Condicoes_Item_03;
  FBAN002CA_Test_03;
  fecharSistemaEco;
  copiaBaseIni('BAN002CA','ECO', '003');
end;

 

 

procedure Geral_Module1;
begin
  removeVariavelProjeto('listaSegundoNivel');
  Project.Variables.descAvancadoGeral := 'Geral_Module1';
  adicionaTesteListaSegundoNivel('teste1');
  adicionaTesteListaSegundoNivel('teste2');
  adicionaTesteListaSegundoNivel('teste3');
  executaTestesListaSegundoNivel('Geral_Module1'); 
end;

 

 

  • Keep in mind "catch" won't catch a simple Log.Error.  That's not an "exception", that's just writing an error to the test log.  There are other things that TestComplete writes out to the test log as errors that also are not exceptions... for example, if a checkpoint fails, that logs an error but it's not going to be trapped by try/catch logic.  This is why, for my test cases, when I want to actually halt the test case and "skip" to the next one, I explicitly raise an exception so that it "bubbles" up to my try/catch logic.  As mentioned, this is probably going to take a bit of re-engineering on your part where you more explicitly control your test cases with this kind of logic. 

     

    As for what you should do with your "OnLogError", I think you need to pull the code out of there that executes the next test case... that really is a bad use of that event handler.  Keep the handler reduced down to handling specific actions that need to be done when logging the error, not in controlling test flow.

     

    As for example, here's kind of a roughed out pseudo-code of what would be done within a single for-loop:

     

    for (var i = 1; i < totalTestCases; i++){
       try{
           testcase[i].Run();
       }
       catch(exception){
            Log.Error('The test case with name ' + testcase[i].Name + ' failed with the following error: ' + exception.message);
       }
    }
    
    //example test cases
    
    function testcase1(){
       //Do something
       //if the test fails
       throw Error('The test case failed because of blah blah blah');
    }
    
    function testcase2(){
       //Do something
       //if the test fails
       throw Error('The test case failed because of blah blah blah');
    }

7 Replies

  • baxatob's avatar
    baxatob
    Community Hero

    Hi,

     

    Can you show how looks your OnLogError handler?

    • jdwather's avatar
      jdwather
      Contributor

       When an error occurs, in my OnLogError I run using the Evaluate the next item in my test list, and only stop execution after running the entire list.

       

      procedure GeneralEvents_OnLogError(Sender; LogParams);
      var descAvancado, descAvancadoGeral : integer;
      begin

            descAvancado :=  Project.Variables.descAvancado

            descAvancadoGeral :=   Project.Variables.descAvancadoGeral


            Inc(Project.Variables.IdItem);
            removeVariavelProjeto('listaNomeRotina');
            fechaAplicativosAbertos;
        
            Evaluate(''+Project.Variables.descAvancado+'');
        
            Inc(Project.Variables.IdAvancado);
            Project.Variables.IdItem := 0;
            removeVariavelProjeto('listaNomeRotina');

       

             if (Project.Variables.descAvancadoGeral = '') then  Runner.Stop(true);


            Evaluate('Controller_Geral.'+Project.Variables.descAvancadoGeral+'');


            Runner.Stop(true);
      end;

      • tristaanogre's avatar
        tristaanogre
        Esteemed Contributor

        I think that's your problem... you're using the OnLogError event handler to control the flow of your test project, from test case to test case, where you're actually using it to execute a test case.  The recursion error you probably have is that, if an error happens in the NEXT test case, taht puts you back into the OnLogError handler, throwing you into a loop.  

         

        I think you may end up needing to do a bit of re-engineering.  In my case, I'm using some try/except/finally logic around my test case executions because, when a test fails for me, I actually raise it as an exception.  So, I hit that try logic, handle the problem in the "catch" block, and then clean up in "finally".  The next test case runs, though, because I'm running a for loop through my test cases.  The try/catch stuff is within that loop.  So... you basically need nested for loops... an outer and an inner.  And, within each, wrap the logic in try/except code so that, if one test case in the loop fails, it will pop out of that test case and let the loop continue.