[MÚSICA] [MÚSICA] Olá, bem vindo ao curso sobre TDD. Eu sou o Clóvis Fernandes e hoje iremos falar sobre Casos de Testes a Partir de Responsabilidades. O problema prático que nós temos normalmente é: como definir os casos de teste de uma aplicação? Esse é problema bastante interessante e difícil de ser feito. Nos exemplos de livros, sites de hands on de geralmente os casos de testes aparecem magicamente. Veja a parte dos enunciados de dois exemplos de katas da internet. O que são katas? Katas vem do karatê. São formas planejadas que você faz cada faixa que você você atua no karatê. São formas para defesa e ataque que você faz e isso é usado também no contexto dos dojos, code dojos, que são os dojos, que são as salas onde se luta o karatê. Os code dojos são as salas onde as pessoas treinam como fazer o desenvolvimento de software no TDD. E nesse exemplo que nós estamos vendo aqui a gente está falando sobre fatores primos. Então, você tem que fatorar número inteiro positivo seus fatores primos. E logo baixo aparece uma tabela já com esses dados mágicos, não é, está certo? Esses dados mágicos que alguém já definiu para você quais são os casos testes, cada linha dessa tabela corresponde a casos teste, está? Isso já foi, alguém já fez isso para você. Como é que isso foi feito? É isso que nós vamos ver. Outro exemplo aqui, esse kata calculadora de string. Você adiciona os números que aparecem numa string, está certo, separados por virgula. Então se você tiver o número, por exemplo como a gente está vendo logo aí baixo, número 1, no string 1, o valor vai ser 1, está certo? Então alguém já definiu isso. Normalmente caso de teste é composto de uma entrada de resultado esperado e depois o resultado real quando você roda o seu programa naquele teste, está certo? Então com essas três coisas eu defino o meu caso de teste. Então aí eu tenho para string vazio a soma vai ser 0 e o meu resultado final tem que dar 0 também e assim por diante. Eu estou mostrando alí, inclusive por exemplo para o string [1,2,3] cujo resultado dever ser 6. Então quando eu rodar tem que dar 6, o resultado real tem que bater com o resultado esperado. Então isso aí são os casos testes. Alguém fez pra mim, se vocês procurarem esse kata calculadora de string eles pedem inclusive para vocês não usarem dados inválidos. Quer dizer, eu estou usando só dados válidos. Isso aí a gente chama de caminho feliz, então a gente está vendo aqui o caminho feliz, está certo? O que é esse caminho feliz? É o caminho, que a gente chama de teste positivo, eu só estou usando os dados corretos. A partir do momento que a pessoa já se treinou nesse kata, aí ele pode começar a trabalhar com dados incorretos e ver o fluxo alternativo não é, conjunto de dados alternativos. Mas vocês percebem que isso aí são dados mágicos não é, aparecem e as pessoas vão fazer. Como que a gente descobre isso não é, está certo? O que que há de comum nesses dois exemplos? Geralmente os exemplos trabalham apenas ou poucos requisitos porque eles são didáticos, eles não podem levar muito tempo, normalmente levam uma hora mais ou menos, 30 minutos, então você não pode usar muitos requisitos. Então geral é requisito, esse do calculadora ele mistura depois lá mais para frente, uns 2, 3 requisitos adicionais complementando esses que eu acabei de colocar aqui agora. Vamos relembrar os requisitos então de cada exemplo. Então nós temos aí para fatores primos, o kata de fatores primos, fatore número inteiro positivo seus fatores primos. O kata calculadora de string, adicione os números que aparece no string separados por vírgula, esses são os 2 requisitos para cada dos katas. Se você olhar apenas para os requisitos não dá pra fazer os testes diretamente. Como é que eu vou definir os casos de teste que trabalham com dados mais precisos não é, está certo? Então é preciso criar os casos de testes, que são os dados que eu vou colocar no meu testes a partir dos requisitos. Então o que a gente chama de casos de teste vão corresponder aos nossos testes que eu vou usar no TDD. Não há mágica, eu preciso obter uma lista de requisitos e obter uma lista de casos de teste para cada requisito levantado. Nós já vimos no que a gente falou, que nós precisamos fazer projeto suficiente. Esse projeto suficiente, o EDUF que a gente está chamando, que não é nem o nome usual da literatura, mas esse projeto suficiente é onde eu vou definir quais são os requisitos mínimos para começar a trabalhar, os requisitos, algumas classes, uma arquitetura inicial, está certo, para poder então dar início. Não há mágica, eu tenho que definir esses requisitos e a partir desses requisitos, a lista de casos de usos para cada deles, onde eu vou definir os dados de testes realmente para poder prosseguir no TDD. Examinando os dois requisitos com mais cuidado, o fatore número inteiro positivo seus fatores primos, adicione os números que aparecem na string separados por vírgula. A gente percebe que de fato eles são o quê? Uma coisa que a gente já estava acostumado, o que que é? Responsabilidades. Eles já são responsabilidades. Essas responsabilidades elas é o que nós já estávamos acostumados a fazer, modelagem CRC não é, está certo e trabalhar com responsabilidades. Então carimbamos isso aí e identificamos que isso são responsabilidades e é isso que nós vamos usar. Responsabilidades, está certo? Nós vamos usar responsabilidades. Com isso, é o que nós vamos fazer, nós vamos exemplificar a obtenção de casos de testes a partir dos requisitos obtidos através da modelagem CRC, na forma de responsabilidades. É isso que nós iremos fazer. Repetindo, não há mágica. Para cada responsabilidade identificada basta obter então a sua lista de casos teste para o caminho feliz inicialmente. A gente chama de positive test, teste positivo ou seja, eu não vou olhar para problemas nas entradas que eu estiver fazendo para esses casos testes iniciais. E depois eu vou fazer, continuo a lista fazendo agora uma lista para o caminho alternativo, o que a gente chama de negative test, está certo? Ou seja agora sim eu vou começar a olhar para dados inválidos. Ao olhar para esses dados inválidos eu certamente vou conseguir definir os casos testes para mim. Nesta aula iremos usar exemplo da literatura, na próxima a gente vai trabalhar uma responsabilidade levantada para a classe biblioteca do SAB, o sistema de automação de biblioteca. É isso que nós vamos fazer posteriormente. A responsabilidade da literatura que eu vou estar usando é simplesmente contar ocorrências de string com apenas caracter uma sentença, que também é string. Ou seja, por exemplo nesse jornal que você estão vendo logo abaixo aqui, eu podia estar querendo procurar string formado apenas pela letra D maiúscula, está certo e eu queria ver a ocorrência. Quanta vezes isso aparece no texto? Eu estaria usando por exemplo método amountOfChar cuja parâmetro seria string string, string para sentença e string para o carácter que eu quero usar, está certo e é isso que eu vou fazer. Qual é o caminho feliz, está certo? O caminho feliz é inicialmente considerar que as entradas sentença e o string correspondente que eu vou procurar nessa sentença são válidos. Essa é primeira característica do caminho feliz. Então eu vou estar chamando de ct1, ct2, ct3, uma sigla numerada para os casos testes, c de casos e t de teste. Então ct1, ct2 e assim por diante, nos vários exemplos que eu dou outras aulas também vai aparecer assim. Então, no ct1 eu tenho string com 1 caractere apenas e uma sentença simples é o que eu vou estar procurando. Então, eu tenho uma sentença no meu exemplo de dado de entrada ali, no caso do teste tudo o que está entre colchetes representa o meu caso teste, da qual eu ali vou gerar o meu código JUnit. Então eu tenho uma sentença com 2 e, então é uma sentença que tem, é string qualquer genérico, não é, mas é uma sentença só, com 2 e e aí eu vou procurar esse string formado pela letra e. Obviamente se eu tenho 2, o meu resultado vai ser 2 esperado e eu espero que o resultado real seja 2. Ou seja quando eu for usar isso no TDD, eu vou testar fazer falhar inicialmente e depois eu vou escrever código que ele reconhece e encontre esses 2 caracteres e dentro desse texto que eu sei que tem 2 e, está certo? O ct2 já é string com outro caractere qualquer, que no caso aqui vai ser o s e uma sentença mais complexa, maior não é, maior tamanho, complexa aqui nesse sentido de maior, está certo? Eu estou querendo aqui, ver se ao fazer isso vai ter alguma alteração no meu código de produção, está certo? Eu vou verificar o string s e espero encontrar 5, porque na minha sentença existem 5 letras s então, eu espero encontrar 5 e o resultado real também deverá ser 5. Se não for, o resultado real não bater com o esperado, a gente diz que houve erro, finaliza erro. O ct3 é string com outra letra, está certo? Que eu estou usando agora 3 sentenças, eu estou aumentando o meu texto. O texto pode ter qualquer tamanho, então eu estou usando nessas 3 aí eu fui aumentando, uma sentença simples, uma sentença maior e depois 3 sentenças, que pode ser simples ou mais complexas está certo? O string que eu quero, o string é o, vai estar composto pelo caractere n eu tenho 3 ocorrências de n e eu vou então, verificar se o, se o meu esperado é 3 encontrar ali e o real é 3. Então vocês percebam que o que está entre colchete já vai corresponder ao caso de teste meu. Então, fica agora muito mais fácil para eu construir o código JUnit correspondente, está certo? Nós mostramos leitura que nós definimos padrão que a gente chama de aaa, que é o arrange, o act e o assert. A gente começa a definir esses casos testes lá no JUnit através do assert e é exatamente para ver se bate com esses dados quando eles são válidos ou inválidos. Agora nós vamos ver o caminho alternativo, o que a gente chama de teste negativo, Negative Testing, ou seja, nós vamos começar a trabalhar com dados inválidos, então o ct4, até ao ct3, tanto a sentença quanto a string, formado de caractere só nesse exemplo não é, esse catálise depois ele passa a ter mais caracteres no string para as buscas de ocorrência. Até o ct3 nós tínhamos sentença e caractere válidos, agora a gente vai começar a introduzir coisas inválidas, então o string a procurar agora, vez de ter 1 caractere como eu defini, vai ter 2 como exemplo, a sentença continua válida, está certo? Então vocês percebam que a minha sentença, o meu caso teste agora é composto de uma sentença válida e de string inválido, ele tem 2 caracteres vez de ter 1 como eu havia determinado. Obviamente, eu espero que ele seja lançado uma excepção e o resultado final tem que ser uma excepção, porque se não for dá erro, significa que eu fiz algum código que não conseguiu capturar esse, essa entrada errônea para o string a se procurar. Já no ct5 vez de 2 caracteres eu estou colocando 3 caracteres, estou procurando 3 caracteres e a sentença continua válida, então eu simplesmente só ampliei o número de caracteres, eu podia ter número maior de caracteres para verificar, eu posso fazer isso para ver se o meu algoritmo, no código de produção, tem alguma variação, está certo? Então a gente pode fazer esses experimentos testando. Eu podia colocar aqui por exemplo, com 15, 20 caracteres, não é, está certo? E ele deve detetar normalmente como deteta se tem 2 caracteres que é mais do que 1, então eu não preciso ficar expandindo, alguns casos é bom fazer isso. Já no ct6, o string a procurar é nulo, a sentença é válida, ou seja, eu estou mandando procurar numa sentença válida, string nulo ou seja, o sistema tem que apontar que não dá para fazer essa busca de ocorrência e ele vai voltar com alguma excepção. Vejam que eu estou pondo excepções, mas cada excepção vai ser uma excepção específica para o tipo de problema que eu estou tendo. Cada dessas linhas que mostram o meu caso teste vai dar margem, provavelmente, a excepções diferentes, está certo? Então o string é nulo, eu vou voltar a uma excepção, eu espero que seja uma excepção apontando que "olha o string é nulo", excepção o string é nulo não dá para fazer essa busca. E obviamente quando eu gerar código real e rodar isso ele vai ter que detetar, se não detetar, erro, aí eu tenho que debugar e arrumar para fazer ele voltar ao mesmo tipo de excepção que eu estou esperando. Já o ct7 o string a procurar é vazio, ou seja, agora como é que eu vou procurar numa sentença válida string vazio? Está certo? Então, vou lançar uma excepção também. Para complementar agora, a sentença na qual eu faço a busca ela é nula inicialmente, no ct8, ela é nula. O string não importa o que ele seja, ele pode até ser nulo, ele pode ser até vazio, não importa, a sentença já é nula, lança uma excepção. Quem é que eu vou indicar que a sentença da qual eu vou fazer uma procura do string de 1 caractere e vai voltar excepção. Já no ct9, a sentença ela é vazia está certo, também não me importa o que é que o string é, se o string é string válido, se o string é vazio, se o string é nulo, não, porque a sentença já é vazia. Então eu boto uma excepção para isso. Provavelmente a excepção vai ser diferente da outra, uma ou outra excepção por causa do, da sentença ser nula e outra excepção porque a sentença é vazia. Com isso, vocês viram que os casos testes eles podem ser definidos a partir de responsabilidades e é isso que nós vamos mostrar na próxima aula, na próxima aula nós vamos usar o exemplo do SABE, o sistema de automação de biblioteca, que fica uma coisa assim pouco mais próxima de vocês, está certo? Porque vocês já viram anteriormente e têm material de leitura com todo o código do SABE feito não é, está certo, inclusivé com os testes correspondentes, lá os testes são de integração não são testes usados para o TDD, são já testes de integração mas dá para verificar como é que eles são feitos. Obrigado [MÚSICA]