Pular para o conteúdo

Os matchers

59 formas de cobrar um valor — e a mensagem que cada uma produz.

Duas formas#

A curta, para os comuns; a encadeada, para o resto. As duas viram a mesma cobrança:

dataforge
crucible "Formas":
    trial "curta":
        expect 2 + 2 is 4

    trial "encadeada":
        expect(2 + 2).to_be(4).to_be_even().to_be_positive()

A curta existe porque quatro de cada cinco cobranças são igualdade, e .to_be(...) em volta delas só acrescenta ruído.

Forma curtaEquivale a
expect x is 4expect(x).to_be(4)
expect x isnt 4expect(x).nao().to_be(4)
expect n bigger 5expect(n).to_be_greater_than(5)
expect n smaller 5expect(n).to_be_less_than(5)
expect s matches "^a"expect(s).to_match("^a")
expect xs has 3expect(xs).to_contain(3)
expect xcobra que valha como verdadeiro

Igualdade#

dataforge
crucible "Igualdade":
    trial "valor":
        expect(4).to_be(4)

    trial "identidade":
        xs := [1, 2]
        expect(xs).to_be_exactly(xs)

    trial "ponto flutuante":
        // 0.1 + 0.2 não dá 0.3 em nenhuma linguagem com IEEE 754
        expect(0.1 + 0.2).to_be_close_to(0.3)

    trial "faixa":
        expect(7).to_be_between(1, 10)

Verdade e vazio#

MatcherPassa quando
to_be_trueé exatamente yes
to_be_falseé exatamente no
to_be_truthyvale como verdadeiro num given
to_be_falsyvale como falso
to_be_voidé void
to_existnão é void
to_be_emptynão tem nenhum item

Tipos#

dataforge
crucible "Tipos":
    trial "pelo nome":
        expect(42).to_be_a("Integer")

    trial "pelos específicos":
        expect(42).to_be_integer().to_be_number()
        expect("a").to_be_text()
        expect([1]).to_be_cluster()
        expect({}).to_be_vault()
        expect(lambda x: x).to_be_action()

to_be_instance_of aceita a linhagem inteira — um herdeiro passa:

dataforge
blueprint Animal:
    action f():
        yield 1

blueprint Cachorro extends Animal:
    action g():
        yield 2

crucible "Linhagem":
    trial "o herdeiro é da mãe também":
        expect(spawn Cachorro()).to_be_instance_of("Animal")

Números#

MatcherMatcher
to_be_greater_thanmaiorto_be_positive> 0
to_be_less_thanmenorto_be_negative< 0
to_be_at_leastto_be_zero= 0
to_be_at_mostto_be_evenpar
to_be_divisible_bysem restoto_be_oddímpar
to_be_finitenem ∞ nem NaNto_be_nané NaN

Texto#

dataforge
crucible "Texto":
    trial "bordas":
        expect("abacate").to_start_with("aba").to_end_with("ate")

    trial "regex":
        expect("ana@x.com").to_match("^[^@]+@[^@]+$")

    trial "conteúdo":
        expect("abacate").to_contain_text("baca")

    trial "forma":
        expect("ABC").to_be_uppercase()
        expect("   ").to_be_blank()

Coleções#

dataforge
crucible "Coleções":
    trial "conteúdo":
        expect([1, 2, 3]).to_contain(2).to_have_length(3)
        expect([1, 2, 3]).to_contain_all([1, 3])
        expect([1, 2, 3]).to_contain_any([9, 2])

    trial "vault":
        expect({"a": 1}).to_have_key("a")
        expect({"a": 1, "b": 2}).to_have_keys(["a", "b"])

    trial "ordem e unicidade":
        expect([1, 2, 3]).to_be_sorted()
        expect([1, 2, 3]).to_be_unique()
        expect([3, 1, 2]).to_have_same_items([1, 2, 3])

    trial "todos e algum":
        expect([2, 4]).to_all_satisfy(lambda n: n % 2 is 0)
        expect([1, 2]).to_any_satisfy(lambda n: n % 2 is 0)

to_have_field serve para vault, record e instância — o teste não deveria precisar saber qual dos três o valor é:

dataforge
record Ponto:
    x: Integer
    y: Integer

crucible "Campo":
    trial "vault":
        expect({"nome": "Ana"}).to_have_field("nome", "Ana")

    trial "record":
        expect(Ponto(1, 2)).to_have_field("x", 1)

Erros#

dataforge
action sacar_demais():
    trigger "saldo insuficiente"

crucible "Erros":
    trial "levanta o tipo esperado":
        expect(lambda => 1 / 0).to_raise(DivisionByZeroError)

    trial "a família também serve":
        expect(lambda => 1 / 0).to_raise(RuntimeError)

    trial "e a mensagem":
        // o corpo de um lambda é uma EXPRESSÃO; para uma instrução,
        // declare uma ação
        expect(sacar_demais).to_raise(mensagem := "saldo")

    trial "não levanta nada":
        expect(lambda => 1 + 1).to_not_raise()

Desempenho e saída#

dataforge
action cumprimentar():
    out "olá"

crucible "Outros":
    trial "prazo":
        expect(lambda => 1 + 1).to_finish_within(100)

    trial "imprime":
        expect(cumprimentar).to_print("olá")

Invertendo#

nao() inverte o próximo matcher — e só ele, para não deixar um estado invertido pendurado:

dataforge
crucible "Negação":
    trial "inverte só o próximo":
        expect([1, 2, 3]).nao().to_contain(9).to_contain(2)

Falhando de propósito#

dataforge
crucible "Manual":
    trial "condição própria":
        Crucible.check(2 + 2 is 4, "a soma quebrou")

    trial "caminho impossível":
        given no:
            Crucible.fail("não deveria chegar aqui")
        expect yes

A lista completa: dataforge crucible --matchers.