O documento discute testes de software, incluindo:
1) Os objetivos dos testes de software e os tipos principais como testes unitários e de integração.
2) Exemplos de como escrever testes unitários usando arranjos, ações e afirmações.
3) A importância de testar os próprios testes através de técnicas como teste de mutação.
3. Instrutor
➔O que vou ser quando crescer;
➔Bacharelado - UTFPR/MD;
➔Mestrado em SI - IPB/PT;
➔Especialização em IA * - UFPR;
➔Fanático por Tecnologia.
6. O que são
Os testes de software são instrumentos utilizados para validar o funcionamento de um
software e tem por propósito mostrar a presença de bugs, e não a ausência.
Para provar que algo é verdade, significa que todas as coisas que são negações dessa sua
afirmação, tem que ser mentira. Se uma delas falharem, a sua afirmação não é verdade. Tem certos
casos que é mais fácil você provar uma inverdade do que um fato, ou seja, prova por refutação.
Exemplo:
Afirmação 1 - Agora está ensolarado no Brasil todo.
FATO 1 - Em todo o Brasil o céu está sem nuvens
FATO 2 - São Paulo é no Brasil
FATO 3 - São Paulo está nublado
7. O que fazem
Fornecem insumos para considerarmos que um programa está suficientemente correto para
o que queremos.
Não é possível eu provar que meu programa não tem bugs se eu não consigo testar todos os
cenários possíveis.
Eu posso afirmar que um programa é incorreto por meio de testes, mas meu teste não pode
afirmar que este programa está correto.
Exemplo:
Cliente solicita um software que retorna o valor de PI.
9. Exemplo Tela 1 - Telefone
Campos:
Código do País
Tipo: Numérico
Regras:
Deve permitir apenas números
Deve ter no máximo 3 dígitos
Obrigatório
Deve ter uma máscara que acrescente o + antes do número (+351, +55)
Código de Area
Tipo: Numérico
Regras:
Deve permitir apenas numeros
Deve ter no máximo 2 dígitos
Obrigatório para alguns países
Telefone
Tipo: Numérico
Regras:
Deve permitir apenas números
Deve permitir 8 ou 9 caracteres
Deve ter uma máscara que acrescente o - (Ex: 9 9999-9999 ou 9999-9999)
10. Exemplo Tela 2 - Nome
Campos:
Nome Completo do Cliente
Tipo: Texto
Regras:
Deve um tamanho máximo 80 caracteres
Deve permitir apenas letras do alfabeto, incluindo acentuação.
Deve ter pelo menos 2 Palavras (Pafúncio Geno)
11. Exemplo Tela 3 - Número do Documento
Botao Cadastrar
Campos:
CPF do cliente
Tipo: Numérico
Regras:
Deve ter um tamanho máximo de 11 caracteres
Deve permitir que seja inserido apenas números
Deve ter uma máscara que acrescente hífens e pontos finais.
(Ex: 000.000.000-00)
Deve ser um CPF válido seguindo o algoritmo validar de CPF
12. Como testar ?
● Coda, builda, testa.
○ Se der erro
■ Coda, builda, testa.
■ Se der erro,
● Coda, builda, testa….
○ Se passar, vai pra proxima feature
● Proxima Feature
■ Coda, builda, testa
● Se der erro,
○ Coda, builda, testa….
● Coda teste
○ Coda funcionalidade
■ Executa teste
■ Se der erro,
● Refatora,
■ ...
Como colocar isso em uma pipeline automatizada ?
Quais cenários foram testados ?
Quais evidências que esses cenários foram testados ?
Como colocar isso em uma pipeline automatizada ?
Quais cenários foram testados ?
Quais evidências que esses cenários foram testados ?
13. Feature Request
Tela 3 - Número do Documento
Botao Cadastrar
Campos:
CPF ou CNPJ do cliente
Tipo: Numérico
Regras:
Deve ter 11 ou 14 caracteres.
Deve permitir que seja inserido apenas números
Deve ter uma máscara que acrescente hífens e pontos finais
(Ex: 000.000.000-00) para CPF ou hífens, pontos finais e barras
para CNPJ (00.000.000/0000-00)
Deve ser um CPF ou CNPJ válido seguindo o algoritmo validador
de CPF/CNPJ
14. Como testar ?
● Coda, builda, testa.
○ Se der erro
■ Coda, builda testa,
■ Se der erro,
● Coda, builda, testa….
○ Se passar, vai pra proxima feature
● Proxima Feature
■ Coda, builda, testa
● Se der erro,
○ Coda, builda, testa….
● Coda teste
○ Coda funcionalidade
■ Executa teste
■ Se der erro,
● Refatora,
■ ...
Como colocar isso em uma pipeline automatizada ?
Quais cenários foram testados ?
Quais evidências que esses cenários foram testados ?
Como colocar isso em uma pipeline automatizada ?
Quais cenários foram testados ?
Quais evidências que esses cenários foram testados ?
15. Testes dos Testes
Mas se o teste é um código e quem escreve o teste unitário é quem escreve o
próprio código, quem testa o teste, quem garante a qualidade dos testes ?
16. Coverage
Mede a abrangência do teste em um código testado.
Em outras palavras, ajuda a descobrir quais trechos de código não estão sendo
testados.
Neste caso, um teste mal feito pode ter coberto um cenário, portanto, a
cobertura de testes não mede a qualidade do seu teste, mas já é um bom início,
pois um código não coberto é pior que um teste mal feito.
Um teste sem validações ainda pode descobrir NullPointers.
Em um dos artigos escritos por Martin Fowler sobre testes, ele indica que o ideal
é ter entre 80 e 90 de cobertura de código, e ainda diz que desconfia de
softwares com 100% de cobertura, pois isso pode induzir desenvolvedores a ter
uma prática de focar sempre em aumentar o coverage ao invés de escrever
testes de qualidade.
20. Teste Unitário - Arrange
@Test
fun shouldReturnValidWhenDocumentHas14Digits() {
val document = "12345678000115"
}
@Test
fun shouldThrowInvalidDocumentExceptionWhenDocumentHasMoreThan14Digits() {
val document = "12345678000115222"
}
@Test
fun shouldThrowInvalidDocumentExceptionWhenDocumentHasLetters() {
val document = "abcdef12345678"
}
21. Teste Unitário - Act
fun shouldReturnTrueWhenDocumentHas14Digits() {
val document = "12345678000115"
validateDocument.execute(document)
}
fun shouldThrowInvalidDocumentExceptionWhenDocumentHasMoreThan14Digits() {
val document = "12345678000115222"
validateDocument.execute(document)
}
fun shouldThrowInvalidDocumentExceptionWhenDocumentHasLetters() {
val document = "abcdef12345678"
validateDocument.execute(document)
}
fun shouldNotPerformDocumentValidationWhenValidationDocumentFeatureIsDisable() {
val document = "12345678000115222"
when(featureFlag.documentValidation).thenReturn(false)
validateDocument.execute(document)
}
22. Teste Unitário - Assert
fun shouldReturnTrueWhenDocumentHas14Digits() {
val document = "12345678000115"
result = validateDocument.execute(document)
verify(validateDocument, times(1)).execute(document)
assertTrue(result)
}
@Test(expected=InvalidDocumentException::class)
fun shouldThrowInvalidDocumentExceptionWhenDocumentHasMoreThan14Digits() {
val document = "12345678000115222"
result = validateDocument.execute(document)
}
fun shouldReturnTrueWhenValidationDocumentFeatureIsDisable() {
val document = "12345678000115222"
when(featureFlag.documentValidation).thenReturn(false)
result = validateDocument.execute(document)
verify(validateDocument, times(1)).execute(any())
assertTrue(result)
}
23. Teste Unitário
Como colocar isso em uma pipeline automatizada ?
Quais cenários foram testados ?
Quais evidências que esses cenários foram testados ?
24. Teste de Integração
Quando uma aplicação necessita consumir (integrar) serviços de outras aplicações, por exemplo:
um App consumindo uma API Rest;
um Microserviço A consumindo recursos de um Microserviço B;
uma aplicação consumindo serviços da AWS,
um banco de dados
25. Teste de Integração
@Test
fun shouldReturnOkWhenCommunicationPerformedSuccessfully() {
val result = testRestTemplate.getForEntity("http://numbersapi.com/random/trivia?json",
RandomNumberResponseDTO::class.java)
val obj: RandomNumberResponseDTO? = result.body;
Assert.assertEquals(HttpStatus.OK, result.statusCode)
Assert.assertTrue(result.hasBody())
Assert.assertTrue(obj?.found!!)
Assert.assertNotNull(obj.text)
Assert.assertNotNull(obj.number)
}
27. Teste de Mutação
Quem testa os testes ? Como identificar malandrinhos que testam sem asserts ?
Escrevemos um outro teste para testar o teste escrito ?
Como funciona ?
28. Teste de Mutação
if (tamanhoMaximo <= 50) {
return
}
Exemplo de uma mutação
if (tamanhoMaximo < 50) {
return
}
29. Teste de Mutação
@Test
fun shouldPerformSuccessfullyWhenValueLenghtIs5() {
val textToBeValidated = "11122"
validateLength.execute(textToBeValidated)
verify(validateLength, times(1)).execute(any())
}
@Test(expected = InvalidDocumentException::class)
fun shouldReturnErrorWheValueLengthIs51() {
val textToBeValidated = "11111111110000000000333333333344444444445555555555#"
validateLength.execute(textToBeValidated)
verify(validateLength, times(1)).execute(any())
}
31. Teste de Mutação
@Test
fun shouldPerformSuccessfullyWhenValueLenghtIs50() {
val textToBeValidated = "11111111110000000000333333333344444444445555555555"
maxLengthX.execute(textToBeValidated)
}