Pessoal,
estava dando uma refatorada no meu projeto para melhorar os códigos de teste e acabei criando um projeto pra auxiliar a escrita dos cenários: o kodo.
Basicamente, ele expõe uma interface fluente com métodos para deixar os códigos de testes simples, legíveis e, claro, totalmente funcionais.
Exemplo:
TestScenario.given(element("name").in(annotation()))
.the(Element::value, Should.be("some name"))
.the(Element::name, Should.be("name"))
.it(Should.NOT_BE_NULL.andThen(Should.notBe(writable())))
.then(attempToChangeValue(), Should.raise(HandlingException.class));
// usando coleções
TestScenario.given(elements().in(annotation()))
.thenIt(Should.NOT_BE_EMPTY)
.each(Should.notBe(writable())) // \
.each(Should.be(readable())) // > itera por todos os elementos
.each(shouldHaveAValue()); // /
O projeto ainda está no início e qualquer ideia será muito bem vinda!
Muito interessante. Algumas coisas que acabei pensando:
por que:
Should.be()
Should.notBe()
Should.raise()
mas shouldHaveAValue() e não Should.haveAValue()?
“Must” não seria um termo mais apropriado?
Acho que o uso do “andThen()” pode ficar ruim quando precisar encadear muitas validações. Se não tiver, talvez seja interessante ter um método que já recebe n validações ao invés de ficar encadeando “anThen(Should.be(andThen(Should.be(…))))”
[quote=regis_hideki]Muito interessante. Algumas coisas que acabei pensando:
por que:
Should.be()
Should.notBe()
Should.raise()
mas shouldHaveAValue() e não Should.haveAValue()?
“Must” não seria um termo mais apropriado?
Acho que o uso do “andThen()” pode ficar ruim quando precisar encadear muitas validações. Se não tiver, talvez seja interessante ter um método que já recebe n validações ao invés de ficar encadeando “anThen(Should.be(andThen(Should.be(…))))”[/quote]
O shouldHaveAValue() foi criado a parte da classe Should. Eu estou pensando em algumas formas de injetar mais métodos aí dentro ou extraí-los pra deixar a sintaxe sempre igual (é mais ou menos por isso que tem o Should.be que recebe um Predicate, aí eu poderia criar um helper como Should.have(aValue())).
Não usei o “Must” porque “Should” é um termo mais usado no BDD.
Quanto ao andThen, é do Java mesmo (das interfaces funcionais), eu vou criar outras interfaces funcionais pra ficar melhor esse código (e prever as checked exceptions também).
Valeu pelas sugestões!
@regis_hideki
dei uma refatorada na DSL. O exemplo que dei acima ficou assim agora:
TestScenario.given(element("name").in(annotation()))
.the(Element::value, should(be("some name")))
.the(Element::name, should(be("name")))
.it(should(notBe(NULL)))
.and(should(notBe(writable())))
.then(attempToChangeValue(), should(raise(HandlingException.class)));
// usando coleções
TestScenario.given(elements().in(annotation()))
.thenIt(should(notBe(EMPTY)))
.each(should(notBe(writable())))
.each(should(be(readable()))
.each(should(have(aValue())));
Eu acho que ficou bem melhor por ter diminuído bastante a quantidade de métodos na API. O único chato mesmo foi o aumento na quantidade de parêntesis no código, mas isso é uma consequência que eu acredito não ser tão negativa (pelo menos por enquanto).