expect(range).to cover(5, 6, 7, 8)
Matchers para verificar a classe de um objeto
Se você estiver escrevendo algum teste que precise verificar de qual classe seu
objeto é, você pode usar os matchers BeAnInstanceOf e BeAKindOf. Eles fun-
cionam do seguinte modo:
# be_an_instance_of verifica se o objeto é uma instância da classe dada
expect(5).to be_an_instance_of(Fixnum)
expect(5).not_to be_an_instance_of(Numeric)
expect(5).not_to be_an_instance_of(String)
# be_a_kind_of verifica se o objeto é uma instância da classe dada ou
# de uma subclasse da classe dada
expect(5).to be_a_kind_of(Fixnum)
expect(5).to be_a_kind_of(Numeric)
expect(5).to be_a_kind_of(Object)
expect(5).not_to be_a_kind_of(String)
Matchers para verificar tamanho de coleção
Se você quer checar o tamanho de uma coleção, você pode usar o Have Matcher.
Na seção 3.2 nós vimos um exemplo de uso desse matcher quando escrevemos o
seguinte teste:
describe BagOfWords do
it "is possible to put words on it" do
bag = BagOfWords.new
bag.put("hello", "world")
expect(bag).to have(2).words
end
end
41
3.6. Matchers relacionados a arrays
Casa do Código
Vamos entender melhor o que a linha expect(bag).to have(2).words faz
por debaixo dos panos:
1) a primeira coisa que o Have Matcher faz é determinar se o objeto sendo tes-
tado é uma coleção ou se ele contém uma coleção.
Para fazer essa checa-
gem ele vê o método que foi passado para o have, no caso acima foi o mé-
todo words, e checa se o objeto sendo testado responde para esse método:
bag.respond_to?(:words);
2) como o objeto bag responde para o método words, o Have Matcher infere que
o objeto bag contém uma coleção e é sobre essa coleção que se quer verificar o
tamanho;
3) finalmente, o Have Matcher verifica o tamanho dessa coleção de acordo com o
tamanho passado na expectation. Como no caso acima o tamanho passado para
o matcher foi 2 ( have(2).words), ele executa bag.words.size == 2.
O Have Matcher precisa fazer toda a lógica acima porque ele serve para testar o
tamanho de uma coleção em dois cenários:
quando você quer verificar o tamanho de uma coleção contida por um objeto,
como no caso acima;
quando você quer verificar o tamanho de uma coleção diretamente.
Abaixo segue um exemplo de uso desse matcher para verificar o tamanho de uma
coleção diretamente:
collection = [1, 2, 3]
expect(collection).to have(3).itens
Um outro detalhe interessante sobre esse matcher é que quando você está fa-
zendo um teste de uma coleção diretamente, você pode passar qualquer método para
ele:
collection = [1, 2, 3]
# todos os modos abaixo funcionam
expect(collection).to have(3).items
expect(collection).to have(3).children
expect(collection).to have(3).things
42
Casa do Código
Capítulo 3. Introdução ao básico do RSpec
Apesar de qualquer método que você passar para o Have Matcher funcionar
quando o objeto sendo testado é uma coleção, é importante que você escolha o mé-
todo que melhor represente a semântica do domínio do seu problema.
Por exemplo, se você estiver fazendo alguma aplicação que é sobre processa-
mento de texto, faz muito mais sentido você escrever um teste como:
words = "hugo"
expect(words).to have(4).letters # letters é um termo do domínio
# do problema
do que um teste como:
words = "hugo"
expect(words).to have(4).items # itens não é um termo do domínio
# do problema
Escolher o método correto como mostramos acima tem duas vantagens. A pri-
meira é que ao escrever código de teste que melhor representa o seu
domínio, você
está seguindo a prática de linguagem ubíqua do Domain Driven Design - DDD,
deixando seu teste mais parecido com uma documentação e também facilitando a
criação de um dicionário de termos padrão para o seu projeto.
A segunda vantagem pode ser vista pela variação entre a mensagem de erro no
teste. Ela é sempre um ótimo indício se você está no caminho de escrever um bom
teste.
Por exemplo, o teste a seguir quebra com a seguinte mensagem:
words = "hugo"
expect(words).to have(3).items
# Failure/Error: expect(words).to have(3).items
#
expected 3 items, got 4
Já o mesmo teste escrito de um modo melhor, quebra com a seguinte mensagem:
words = "hugo"
expect(words).to have(3).letters
43
3.6. Matchers relacionados a arrays
Casa do Código
# Failure/Error: expect(words).to have(3).letters
#
expected 3 letters, got 4
Perceba como a mensagem de erro ficou melhor quando usamos um método
mais apropriado para descrever a intenção do nosso teste.
Por fim, você pode usar mais duas formas desse matcher, que são as formas
have_at_least e have_at_most. Segue um exemplo usando essas duas formas:
collection = [1, 2, 3, 4, 5]
expect(collection).to have_at_least(3).elements
expect(collection).to have_at_most(5).elements
Matcher para verificar mudança de estado ou valor
Imagine que você está desenvolvendo um jogo e precise criar um objeto que
tem uma máquina de estados, por exemplo, para trackear se o jogo já começou ou
não. Você quer que o objeto tenha um método Game#start que ao ser disparado,