Sobre o teste de software

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

Avatar do usuário
Vlademiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 752
Registrado em: 11 Jul 2005 02:46

Sobre o teste de software

Mensagem por Vlademiro »

Pessoal, andei procurando algo no fórum sobre teste de software e não encontrei nada sobre o assunto. Por isso resolvi postar a minha experiência.

Quando comecei a programar, o teste de software realizado era o velho "teste de mesa", onde o programador mesmo ia inserindo valores e testando a sua rotina antes de liberá-la para a produção. Ele ainda existe, mas de lá para cá a coisa mudou muito, pois somente o "teste de mesa" não é mais o suficiente. Agora os testes são automatizados e não são mais efetuados após a rotina ser desenvolvida, ela faz parte do processo de desenvolvimento. Andei lendo sobre o assunto, pesquisando outras linguagens e desenvolvi a minha própria classe de testes. Como ela é feita em Harbour resolvi postar no tópico Harbour mesmo.

Código: Selecionar todos

REQUEST HB_LANG_PT

REQUEST HB_CODEPAGE_UTF8
REQUEST HB_CODEPAGE_UTF8EX


FUNCTION MAIN()
LOCAL oTest := TVladTest():New()

      // Seleciono a lingua portuguesa e seus caracteres
      HB_LANGSELECT( 'PT' )
      HB_CDPSELECT( "UTF8EX" )

      oTest:TestOn()
      oTest:Title( "Testes : a ideia geral" )

      oTest:H1( "1 + 1 = 2" )
      oTest:Test( "1 + 1 = 2" , 1 + 1 = 2 , .t. )


      oTest:H1( "Um erro proposital para ver como se comporta 2 + 2 = 3" )
      oTest:Test( "2 + 2 = 3" , 2 + 2 = 3 , .t. )

      oTest:Close()

RETURN NIL

A ideia é simples, você passa para o método uma breve descrição, o valor retornado e o valor esperado para que o teste seja validado. O método vai fazer as comparações e retornar se deu certo ou não.

Só postei um exemplo simples (veja arquivo anexo), mas se vcs quiserem posso ir detalhando a classe com outros exemplos.

:xau
Anexos
test0.zip
(3.7 KiB) Baixado 55 vezes
Avatar do usuário
Vlademiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 752
Registrado em: 11 Jul 2005 02:46

Sobre o teste de software

Mensagem por Vlademiro »

Esqueci de postar a tela . Segue em anexo...
test0.png
test0.png (5.27 KiB) Exibido 861 vezes
Esse MAIN / 19 e MAIN / 23 é o ponto, na rotina anterior, onde a rotina é chamada.
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Sobre o teste de software

Mensagem por JoséQuintas »

Se a gente souber aonde vai dar erro, nem precisa de teste.... rs

No geral eu coloco no aplicativo pra me gerar avisos.
Pra abrir arquivo, caso eu tenha esquecido de abrir, e já registrar como erro pra ser corrigido.
Pra me avisar caso tenha uma atualização que não precisa mais, me avisando que ela já foi feita.
Se algum lançamento gere reserva negativa no produto, o que não pode existir.
Etc.

Conforme vou detectando o que pode me ajudar, vou colocando no aplicativo.

E o principal:
Se tiver que dar erro, vai dar. Não escondo erros, abre uma janela grande com a mensagem de erro.
O erro ocorre e o aplicativo me avisa por email.
Desta forma, todos os erros ficam resolvidos.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
Vlademiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 752
Registrado em: 11 Jul 2005 02:46

Sobre o teste de software

Mensagem por Vlademiro »

Quintas, acho essa sua técnica muito boa, e destaco dois pontos positivos :

( 1 ) Um log de erro sempre é gerado quando algum evento ocorre e o desenvolvedor sempre é notificado. Por exemplo : saldo negativo.

( 2 ) A transparência com que você trata o erro. Não escondendo-o do seu cliente. Essa atitude, em vez de enfraquecer o relacionamento com o cliente, faz é fortalecer.

Mas vou apresentar uma crítica construtiva, tiradas do livro "A prátida da Programação" de Kernighan e Pike :

( 1 ) Testar e depurar quase sempre são utilizados na mesma frase, mas eles não são a mesma coisa. Para simplificar, a depuração é aquilo que você faz quando sabe que um programa está com problemas. O teste é uma tentativa de QUEBRAR um programa que você acha que está funcionando. As funções que você criou são importantes sim, mas pertencem a fase de depuração.

(2 ) O teste demonstra a presença de bugs, mas não a sua ausência. Ou seja, o teste não resolve todos os problemas. Ele é uma tentativa (não garantida) de minimizar os erros.

Sei que o tempo é nosso inimigo e testar uma aplicação consome tempo, mas creio que um teste automático dentro de cada função/método irá fazer com que esse tempo NÃO SEJA extenso.

Vou postar mais alguns exemplos durante a semana dentro desse tópico.
Avatar do usuário
Vlademiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 752
Registrado em: 11 Jul 2005 02:46

Sobre o teste de software

Mensagem por Vlademiro »

A classe de testes gera um arquivo chamado test.log , esse arquivo é preenchido com todos os resultados dos testes. O arquivo test.log não é apagado, assim sempre que alguma função ou método usar a classe de testes, esse arquivo irá sendo preenchido.

Código: Selecionar todos



REQUEST HB_LANG_PT

REQUEST HB_CODEPAGE_UTF8
REQUEST HB_CODEPAGE_UTF8EX


FUNCTION MAIN()
LOCAL oTest := TVladTest():New()

      // Seleciono a lingua portuguesa e seus caracteres
      HB_LANGSELECT( 'PT' )
      HB_CDPSELECT( "UTF8EX" )

      oTest:TestOn()
      oTest:Title( "Testes : o método AddResult" )

      oTest:H1( "1 + 1 = 2" )
      oTest:AddResult( "Essa mensagem não irá aparecer." )
      oTest:AddResult( "O teste não apresentou falhas." )
      oTest:Test( "1 + 1 = 2" , 1 + 1 = 2 , .t. )


      oTest:H1( "Um erro proposital para ver como se comporta 2 + 2 = 3" )
      oTest:AddResult( "Essa mensagem irá aparecer porque o próximo teste irá notificar uma falha." )
      oTest:AddResult( "É importante para não poluir a tela com mensagens adicionais de testes que não geraram falha." )
      oTest:Addresult( "www.pctoledo.com.br/forum"  , "Aceitam outros parâmetros" , .t. , Date() , 1200  )
      oTest:Test( "2 + 2 = 3" , 2 + 2 = 3 , .t. )

      oTest:Info( "Uma informação que sempre será exibida, independente do teste falhar ou não" )
      oTest:Info( "Aceito vários parâmetros" , 1 , .t. , date() , 123.45 )


      oTest:Close()

RETURN NIL

O método ::AddResult serve para acumular notificações diversas. Ele, internamente, é uma matriz que vai sendo preenchida até que o próximo método ::Test retorne falso. Isso impede que a sua tela ou seu arquivo test.log fique muito cheio com informações adicionais que não irão acrescentar nada. Sempre que o método ::Test é chamado ele exibe ou não os resultados coletados por ::AddResult e depois zera a matriz.

O método Info serve para exibir informações, independente do teste falhar ou não.

Mas fica a pergunta : Tudo isso não é muito trabalhoso ?

Eu acho que sim, fica muito trabalhoso. Mas existem formas de minimizar esse trabalho, desde que a gente insira esses testes dentro de cada função ou método. Conforme espero postar adiante.

Caso alguém queira compilar esse exemplo, basta usar a classe TVladTest que eu postei anteriormente.
Avatar do usuário
Vlademiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 752
Registrado em: 11 Jul 2005 02:46

Sobre o teste de software

Mensagem por Vlademiro »

A tela com o exemplo anterior fica assim :
test1.png
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Sobre o teste de software

Mensagem por JoséQuintas »

Um pedido confirmado faz diversas atualizações no banco de dados.
E depende de como estiver configurada a transação.
Caso seja "desconfirmado", todas as atualizações deveriam ser desfeitas.

A teoria é boa, mas na prática não vejo como isso poderia ser testado automaticamente.

O Harbour tem algo nesse sentido, pra ver se os cálculos e outras operações ocorrem do jeito que deveria.
De qualquer forma, é algo parcial, não confirma se está tudo realmente ok.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
Vlademiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 752
Registrado em: 11 Jul 2005 02:46

Sobre o teste de software

Mensagem por Vlademiro »

Veja esse exemplo a seguir.

Eu posso instanciar o objeto dentro de uma classe e ela sempre irá monitorar o que está acontecendo.

Código: Selecionar todos

METHOD NEW(  cDatabaseType, cDatabaseAddress, cDatabaseName, cDatabaseUser, cDatabasePassword, cDatabasePort    ) CLASS TVladSQL

   ::oTest := TVladTest():New(  "TVladSQL():New()"   )  // Instancia o teste internamente

   ... // Resto do método
   ::Open() // Veja o proximo trecho onde tem esse método (logo abaixo)

RETURN Self

Código: Selecionar todos

/****m* TVladSQL/Open
*
* NAME
*    Open
*
* DESCRIPTION
*    Open connect with database
*
* SOURCE
*/
METHOD Open() CLASS  TVladSQL
LOCAL nPort

     DO CASE
        CASE ::cDatabaseType = "PostgreSQL"

            ::oTest:Info( "..." ) // Aqui eu gero notificações <==============================
            ::cDatabasePort := hb_DefaultValue( ::cDatabasePort , "5432" )
            IF ValType( ::cDatabasePort ) == "N"
               nPort := ::cDatabasePort
            ELSEIF ValType( ::cDatabasePort ) == "C"
               nPort := VAL( ::cDatabasePort )
            ENDIF

            ::oServer := TPQServer():New( ::cDatabaseAddress, ::cDatabaseName , ::cDatabaseUser, ::cDatabasePassword , nPort   )

            IF ::oServer:NetErr()
              ::lIsOpen := .f.
              ::cErrorMsg := ::oServer:ErrorMsg()
            ELSE
              ::lIsOpen := .t.
              ::oServer:SetVerbosity( 2 )
              ::oServer:traceon( "simple.log" )
            ENDIF
     ENDCASE
     ::oTest:AddResult( "Error message : " , ::cErrorMsg ) // <================================== Aqui também e logo abaixo nas 2 próximas linhas
     ::oTest:AddResult( "Config data   : " , " Address : " + ::cDatabaseAddress + " Databasename : " + ::cDatabaseName )
     ::oTest:Test( "Connect server" , ::lIsOpen , .t. ) // Se não passar grava no arquivo que falhou e adiciona os resultados coletados acima.

RETURN ::lIsOpen
/*****/
Feito isso eu posso criar uma rotina para testar esse método sob diversas condições, conforme o código abaixo.
Sempre que eu mudar algo no sistema eu rodo essa rotina para ver se ela não gera um alerta nos logs

Código: Selecionar todos

***
/*
     TEST EXEC  (Test_Exec)
*/
***
STATIC FUNCTION TVladSQL_Test_Exec()
LOCAL oTest := TVladTest():New( "Test_Exec / Execute command SQL in database" )
LOCAL cSQL

  oTest:TestOn()
  oTest:Title()

  oTest:H1( "Execute drop table if exists" )
  cSQL := "DROP TABLE  IF EXISTS test1"
  TVladSQL_Test_Exec_Main( oTest , cSQL )

  oTest:H1( "Execute create table" )  //----------------------> Condição 1 (Tudo certo!)
  cSQL := "CREATE TABLE test1 ( test varchar(50) )"
  TVladSQL_Test_Exec_Main( oTest , cSQL )

  oTest:H1( "Execute create table with error" ) // --------------------------> Condição 2 (Erro na digitação de um comando. Como o método se comporta ?)
  cSQL := "CREATES ERRO PROPOSITAL NO MEIO DA SENTENCA TABLE test1 ( test varchar(50) )"
  TVladSQL_Test_Exec_Main( oTest , cSQL )

  // Posso ter outras condições aqui

RETURN NIL
*** Aqui é a função de testes
STATIC FUNCTION TVladSQL_Test_Exec_Main( oTest , cSQL  )
LOCAL oSQL

  oTest:TestOn()
  oSQL := TVladSQL():New()
  oSQL:TestOn()
  oTest:Test(  "Open connection" , oSQL:IsOpen() , .t. )
  oSQL:Close()


RETURN NIL
Isso também pode ser feito dentro de funções.

Eu só estou postando a ideia geral. Existem casos particulares, como o cancelamento de baixa de pedido, que talvez não possa ser monitorada por testes. Mas desde que eu tenha coletado as diversas situações que acontecem eu posso criar um ambiente de testes e usar o log gerado dentro dos métodos ou funções.

Não é perfeito, mas para mim tem funcionado e me mostrado alguns erros bem difíceis de serem achados. Mais do que isso, ela me ajuda a antecipar algumas situações chatas.

Só não deixo ela gerando o arquivo de logs sempre pois acho que deixaria o sistema lento. Mas para testar eu sempre utilizo.
Avatar do usuário
Vlademiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 752
Registrado em: 11 Jul 2005 02:46

Sobre o teste de software

Mensagem por Vlademiro »

Quintas, vc disse que o harbour já tem alguma coisa nesse sentido. O que é ? Será que eu reinventei a roda ? :-o
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Sobre o teste de software

Mensagem por JoséQuintas »

O Harbour tem um ou mais programas de teste, só pra executar e confirmar se o Harbour gerado está funcionando do jeito que deveria.
Alguns cálculos, conversões, e velocidade.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
Vlademiro
Usuário Nível 4
Usuário Nível 4
Mensagens: 752
Registrado em: 11 Jul 2005 02:46

Sobre o teste de software

Mensagem por Vlademiro »

Entendi.

O teste que o harbour faz é de outra natureza. Ele fica gerando estatísticas sobre o executável.
Responder