Página 1 de 1
Sobre o teste de software
Enviado: 18 Jun 2016 20:57
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
Sobre o teste de software
Enviado: 18 Jun 2016 21:03
por Vlademiro
Esqueci de postar a tela . Segue em anexo...

- test0.png (5.27 KiB) Exibido 856 vezes
Esse MAIN / 19 e MAIN / 23 é o ponto, na rotina anterior, onde a rotina é chamada.
Sobre o teste de software
Enviado: 18 Jun 2016 23:03
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.
Sobre o teste de software
Enviado: 19 Jun 2016 10:56
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.
Sobre o teste de software
Enviado: 19 Jun 2016 11:25
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.
Sobre o teste de software
Enviado: 19 Jun 2016 11:28
por Vlademiro
A tela com o exemplo anterior fica assim :
Sobre o teste de software
Enviado: 19 Jun 2016 13:40
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.
Sobre o teste de software
Enviado: 19 Jun 2016 17:01
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.
Sobre o teste de software
Enviado: 19 Jun 2016 17:05
por Vlademiro
Quintas, vc disse que o harbour já tem alguma coisa nesse sentido. O que é ? Será que eu reinventei a roda ?

Sobre o teste de software
Enviado: 19 Jun 2016 20:15
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.
Sobre o teste de software
Enviado: 19 Jun 2016 22:29
por Vlademiro
Entendi.
O teste que o harbour faz é de outra natureza. Ele fica gerando estatísticas sobre o executável.