defmoduleStudentsTestdouseExUnit.Case test "adding a new user on approved list"do current_list = ["Paulo","João"] students = ["Iago"] assert Students.add_to_approved_list(current_list, students) == ["Paulo","João","Iago"]endend
mixtesttest/students_test.exswarning:Students.add_to_approved_list/2isundefined (module Studentsisnotavailableorisyettobedefined)test/students_test.exs:9:StudentsTest."test List of students approved adding a new user on approved list"/11) test List of students approved adding a new user on approved list (StudentsTest)test/students_test.exs:5 ** (UndefinedFunctionError) function Students.add_to_approved_list/2 is undefined (module Students is not available)
code:assertStudents.add_to_approved_list(current_list,students) == ["Paulo", "João","Iago"]stacktrace:Students.add_to_approved_list(["Paulo","João"], ["Iago"])test/students_test.exs:9: (test)Finishedin0.02seconds (0.00s async,0.02ssync)1test,1failure
defmoduleStudentsdodefadd_to_approved_list(_,_) do []endend
Criamos o módulo Students e dentro a função add_to_approved/2. Como já tinhamos falado, retornaremos uma lista.
mixtesttest/students_test.exsCompiling1file (.ex)1) test List of students approved adding a new user on approved list (StudentsTest)test/students_test.exs:5Assertionwith==failedcode:assertStudents.add_to_approved_list(current_list,students) == ["Paulo", "João","Iago"]left: []right: ["Paulo", "João","Iago"]stacktrace:test/students_test.exs:9: (test)Finishedin0.01seconds (0.00s async,0.01ssync)1test,1failure
defmoduleStudentsdodefadd_to_approved_list(current_list,_) do current_listendend
Vamos executar novamente o teste:
mixtesttest/students_test.exsCompiling1file (.ex)1) test List of students approved adding a new user on approved list (StudentsTest)test/students_test.exs:5Assertionwith==failedcode:assertStudents.add_to_approved_list(current_list,students) == ["Paulo", "João","Iago"]left: ["Paulo", "João"]right: ["Paulo", "João","Iago"]stacktrace:test/students_test.exs:9: (test)Finishedin0.01seconds (0.00s async,0.01ssync)1test,1failure
Estamos chegando perto! Agora acusou apenas que não temos o estudante Iago em nossa lista. Isso porque o primeiro parâmetro de nossa função esta passando apenas uma lista sem Iago. Já o segundo parâmetro está passando uma lista e nessa lista possuÃmos o nome Iago. Essa segunda lista são os estudantes que queremos adicionar na lista de estudantes que passaram. Precisamos unir essas duas listas. Para isso, podemos usar o operador ++/2 do elixir.
lib/students.ex
defmoduleStudentsdodefadd_to_approved_list(current_list, new_students) do current_list ++ new_studentsendend
Alteramos o nome do segundo parâmetro de underline (_) para new_students para podermos usar em nossa função. Tendo os novos estudantes em mãos, adicionamos o operador ++/2 ao lado de current_list e colocamos ao final a lista que queremos fazer a união, no nosso casso new_students. Vamos rodar novamente nosso teste:
Agora temos uma nova lista retornada pela função add_to_approved_list/2 contendo a união de duas listas. Com isso temos dois dos problemas resolvidos.
Ter uma lista de estudando aprovados
Conseguir adicionar estudantes nessa lista
Remover estudantes da lista.
Precisamos agora remover os estudantes que foram desaprovados. Vamos ao teste:
test/students_test.exs
defmoduleStudentsTestdouseExUnit.Case test "removing a user on approved list"do current_list = ["Paulo","João"] students = ["João"] assert Students.remove_from_approved_list(current_list, students) == ["Paulo"]endend
mixtesttest/students_test.exsCompiling1file (.ex)warning:Students.remove_from_approved_list/2isundefinedorprivatetest/students_test.exs:16:StudentsTest."test List of students approved removing an user on approved list"/11) test List of students approved removing an user on approved list (StudentsTest)test/students_test.exs:12** (UndefinedFunctionError) functionStudents.remove_from_approved_list/2 is undefined or privatecode:assertStudents.remove_from_approved_list(current_list,students) == ["Paulo"]stacktrace: (hello_world0.1.0) Students.remove_from_approved_list(["Paulo","João"], ["João"])test/students_test.exs:16: (test).Finishedin0.02seconds (0.00s async,0.02ssync)2tests,1failure
Vamos adicionar mais uma tarefa. Queremos saber a quantidade de estudantes que passaram no vestibular. Vamos ao teste:
test/students_test.exs
defmoduleStudentsTestdouseExUnit.Case describe "List of students approved"do test "total approved"do current_list = ["Paulo","João"] assert Students.total_approved(current_list) ==2endendend
mixtesttest/students_test.exswarning:Students.total_approved/1isundefinedorprivate.Didyoumean:*add_to_approved_list/2test/students_test.exs:22:StudentsTest."test List of students approved total approved"/1.1) test List of students approved total approved (StudentsTest)test/students_test.exs:19** (UndefinedFunctionError) functionStudents.total_approved/1 is undefined or private. Did you mean:*add_to_approved_list/2code:assertStudents.total_approved(current_list) ==2stacktrace: (hello_world0.1.0) Students.total_approved(["Paulo","João"])test/students_test.exs:22: (test).Finishedin0.03seconds (0.00s async,0.03ssync)3tests,1failure
Não possuÃmos a função. Logo, temos um erro. Vamos resolver isso criando ela:
Quando lidamos com totais, sempre esperamos um integer, para manter consistente retornamos dessa função apenas 2 para nosso teste passar. Vamos ver o que o teste nos diz.
Vamos adicionar uma outra assertion para nosso teste, com uma quantidade diferente de itens na lista. Isso garante que ela funciona bem.
test/students_test.exs
defmoduleStudentsTestdouseExUnit.Case describe "List of students approved"do test "total approved"do current_list = ["Paulo","João"] another_current_list = ["Carlos","Cris","Jill"] assert Students.total_approved(current_list) ==2 assert Students.total_approved(another_current_list) ==3endendend
Vamos rodar o teste com a nova assertion:
mixtesttest/students_test.exs..1) test List of students approved total approved (StudentsTest)test/students_test.exs:19Assertionwith==failedcode:assertStudents.total_approved(another_current_list) ==3left:2right:3stacktrace:test/students_test.exs:24: (test)Finishedin0.02seconds (0.00s async,0.02ssync)3tests,1failure
defmoduleStudentsTestdouseExUnit.Case describe "List of students approved"do test "was student approved?"do current_list = ["Iago","Paulo","João"] assert Students.was_approved?(current_list,"Iago") ==trueendendend
mixtesttest/students_test.exswarning:Students.was_approved?/2isundefinedorprivate.Didyoumean:*total_approved/1test/students_test.exs:30:StudentsTest."test List of students approved was student approved?"/1...1) test List of students approved was student approved? (StudentsTest)test/students_test.exs:27** (UndefinedFunctionError) functionStudents.was_approved?/2 is undefined or private. Did you mean:*total_approved/1code:assertStudents.was_approved?(current_list,"Iago") ==truestacktrace: (hello_world0.1.0) Students.was_approved?(["Iago","Paulo","João"],"Iago")test/students_test.exs:30: (test)Finishedin0.03seconds (0.00s async,0.03ssync)4tests,1failure
Vamos adicionar agora um caso de que o estudante que procuramos não passou.
test/students_test.exs
defmoduleStudentsTestdouseExUnit.Case describe "List of students approved"do test "was student approved?"do current_list = ["Iago","Paulo","João"] assert Students.was_approved?(current_list,"Iago") ==true assert Students.was_approved?(current_list,"Rui") ==falseendendend
Para isso, apenas adicionamos a linha 9 a nosso teste, procuranod por um estudante chamado Rui que não existe em nossa lista. Vamos rodar o teste:
mixtesttest/students_test.exs..1) test List of students approved was student approved? (StudentsTest)test/students_test.exs:27Assertionwith==failedcode:assertStudents.was_approved?(current_list,"Rui") ==falseleft:trueright:falsestacktrace:test/students_test.exs:31: (test).Finishedin0.03seconds (0.00s async,0.03ssync)4tests,1failure
Temos um operador em elixir chamado in/2. Ele verificar se existe um elemento em nossa lista. A leitura desse operador fica muito interessante: 1 in [1,2,3]. Vamos aplica-lo em nosso código:
defmoduleStudentsdo# ...defwas_approved?(approved_list, student) do student in approved_listendend
Perfeito! As funções de lista para estudantes estão tomando forma e ficando claras em seus objetivos. Precisamos so de mais duas funcionalidades. Me ligaram ainda pouco pedindo que adicionacemos a possibilidade de saber o primeiro e ultimo estudante de nossa lista. Falei que não seria um problema, que você já estava dominando a listagem. Vamos escopar isso
Desafio final
Obter primeiro estudante da lista
Obter último estudante da lista
Vamos começar do primeiro. Criaremos seu teste:
test/students_test.exs
defmoduleStudentsTestdouseExUnit.Case describe "List of students approved"do# ... test "first the list"do current_list = ["Iago","Paulo","João"] assert Students.first(current_list) =="Iago"endendend
mixtesttest/students_test.exswarning:Students.first/1isundefinedorprivatetest/students_test.exs:37:StudentsTest."test List of students approved first the list"/1.1) test List of students approved first the list (StudentsTest)test/students_test.exs:34** (UndefinedFunctionError) functionStudents.first/1 is undefined or privatecode:assertStudents.first(current_list) =="Iago"stacktrace: (hello_world0.1.0) Students.first(["Iago","Paulo","João"])test/students_test.exs:37: (test)...Finishedin0.03seconds (0.00s async,0.03ssync)5tests,1failure
Simples não? Agora precisamos lidar com o útilmo da lista. Te desafio a pensar qual função usaremos para resolver isso. Enquanto pensa, vamos para o teste:
test/students_test.exs
defmoduleStudentsTestdouseExUnit.Case describe "List of students approved"do# ... test "last in the list"do current_list = ["Iago","Paulo","João"] assert Students.last(current_list) =="João"endendend
mixtesttest/students_test.exswarning:Students.last/1isundefinedorprivatetest/students_test.exs:43:StudentsTest."test List of students approved last in the list"/1...1) test List of students approved last in the list (StudentsTest)test/students_test.exs:40** (UndefinedFunctionError) functionStudents.last/1 is undefined or privatecode:assertStudents.last(current_list) =="João"stacktrace: (hello_world0.1.0) Students.last(["Iago","Paulo","João"])test/students_test.exs:43: (test)..Finishedin0.03seconds (0.00s async,0.03ssync)6tests,1failure
Vamos implementar a função que não existe. Pensou na função que usariamos para ser oposto a List.first/1? É isso mesmo, List.last/1. Vamos implementar nosso código.
Ótimo! Agora temos muitas ferramentas para lidar com listas. Listas são simples, mas podemos tirar grandes vantagens dela ao dia-a-dia de trabalho. Ela sempre estará presente e muitas vezes podem se tornar bem complexa. O domÃnio de operações e funções de auxÃlio ira te ajudar na jornada.
Você deve ter ficado com a impressão de faltar algo. Sim, temos um buraco aqui. Que tipo de aprendizado de lista não ensina como a percorremos. Por isso o próximo capÃtulo falará sobre estruturas de repetição.