public void testClass() {
Class cls = DateTimeUtils.class;
assertEquals(true, Modifier.isPublic(cls.getModifiers()));
assertEquals(false, Modifier.isFinal(cls.getModifiers()));
assertEquals(1, cls.getDeclaredConstructors().length);
assertEquals(true, Modifier.isProtected(
cls.getDeclaredConstructors()[0].getModifiers()));
DateTimeUtils utils = new DateTimeUtils() {};
}
Meh...
Sim, e esse é um bom exemplo!
Mestre em Ciência da Computação
Desenvolvedor e instrutor na Caelum
public void testClass() {
Class cls = DateTimeUtils.class;
assertEquals(true, Modifier.isPublic(cls.getModifiers()));
assertEquals(false, Modifier.isFinal(cls.getModifiers()));
assertEquals(1, cls.getDeclaredConstructors().length);
assertEquals(true, Modifier.isProtected(
cls.getDeclaredConstructors()[0].getModifiers()));
DateTimeUtils utils = new DateTimeUtils() {};
}
Vossa mensagem apeteceu-me de tal forma que demonstrarei publicamente meu regozijo apertando o botão de meu dispositivo de apontamento sobre esta região do documento.
Curtir
Vossa mensagem apeteceu-me de tal forma que demonstrarei publicamente meu regozijo apertando o botão de meu dispositivo de apontamento sobre esta região do documento.
versusCurtir
assertEquals(true, Modifier.isPublic(cls.getModifiers()));
assertEquals(false, Modifier.isFinal(cls.getModifiers()));
versus
assertThat(cls, both(isPublic(), not(isFinal())));
+ curto
=
+ conciso
testClass
versusclassIsPublicNotFinalWithOneProtectedConstructor
public void canProvideCustomRequestScopedComponents() {
checkAvailabilityFor(false,
Arrays.<Class<?>>asList(MyRequestComponent.class));
}
Mas...
(mais legível)
public void testClass() {
Class cls = DateTimeUtils.class;
assertEquals(true, Modifier.isPublic(cls.getModifiers()));
assertEquals(false, Modifier.isFinal(cls.getModifiers()));
assertEquals(1, cls.getDeclaredConstructors().length);
assertEquals(true, Modifier.isProtected(
cls.getDeclaredConstructors()[0].getModifiers()));
DateTimeUtils utils = new DateTimeUtils() {};
}
5 gets!
public void testClass() {
Class cls = DateTimeUtils.class;
assertTrue(isPublic(cls));
assertFalse(isFinal(cls)));
assertTrue(hasOnlyConstructors(cls, protectedConstructor));
DateTimeUtils utils = new DateTimeUtils() {};
}
private boolean isPublic(Class cls) {
return Modifier.isPublic(cls.getModifiers());
}
private boolean isFinal(Class cls) {
return Modifier.isFinal(cls.getModifiers());
}
private boolean hasOnlyConstructors(Class cls,
MyConstructorDescriptionClass... constructors) {
if (constructors.length != cls.length) {
return false;
}
// código meio feio aqui
}
public void testClass() {
Class cls = DateTimeUtils.class;
assertTrue(isPublic(cls));
assertFalse(isFinal(cls)));
assertTrue(hasOnlyConstructors(cls, protectedConstructor));
DateTimeUtils utils = new DateTimeUtils() {};
}
public void testClass() {
Class cls = DateTimeUtils.class;
assertTrue(isPublic(cls));
assertFalse(isFinal(cls)));
assertTrue(hasOnlyConstructors(cls, protectedConstructor));
DateTimeUtils utils = new DateTimeUtils() {};
}
Boa prática: nomes claros
public void classIsPublicNotFinalWithOneProtectedConstructor() {
Class cls = DateTimeUtils.class;
assertTrue(isPublic(cls));
assertFalse(isFinal(cls)));
assertTrue(hasOnlyConstructors(cls, protectedConstructor));
DateTimeUtils utils = new DateTimeUtils() {};
}
Má prática: não seguir a convenção da linguagem
Boa prática: quebrar as regras quando isso te ajudar
public void class_is_public_not_final_with_one_protected_constructor() {
Class cls = DateTimeUtils.class;
assertTrue(isPublic(cls));
assertFalse(isFinal(cls)));
assertTrue(hasOnlyConstructors(cls, protectedConstructor));
DateTimeUtils utils = new DateTimeUtils() {};
}
it "should update timestamp if last updated more than one day ago" do
@job.attributes = valid_job_attributes
@job.updated_at = 2.days.ago
Job.record_timestamps = false
@job.save
Job.record_timestamps = true
updated_at = @job.updated_at
@job.update_attributes :title => 'teste'
@job.updated_at.should_not eql(updated_at)
@job.title.should eql('teste')
end
it "should update timestamp if last updated more than one day ago" do
two_days_ago = 2.days.ago
@job.attributes = valid_job_attributes
@job.updated_at = two_days_ago
@job.save_without_timestamps
@job.update_attributes :title => 'teste'
@job.updated_at.should_not eql(two_days_ago)
@job.title.should eql('teste')
end
it "should update timestamp if last updated more than one day ago" do
two_days_ago = 2.days.ago
@job.attributes = valid_job_attributes
@job.updated_at = two_days_ago
@job.save_without_timestamps
@job.update_attributes :title => 'teste'
@job.updated_at.should_not eql(two_days_ago)
@job.title.should eql('teste')
end
public void mostraTarefasDoUsuario() {
Tarefa atrasada = ... // cria a tarefa
Tarefa hoje = ... // cria a tarefa
Tarefa amanha = ... // cria a tarefa
Page currentPage = browser.currentPage();
assertTrue(currentPage.div("tarefa_atrasada_" + atrasada.getId())
.exists());
assertTrue(currentPage.div("tarefa_hoje_" + hoje.getId())
.exists());
assertTrue(currentPage.div("tarefa_prox_" + amanha.getId())
.exists());
}
Hmm... ok! :)
public void someComTarefaJaPronta() {
Tarefa atrasada = ... // cria a tarefa
Tarefa hoje = ... // cria a tarefa
Tarefa amanha = ... // cria a tarefa
Page currentPage = browser.currentPage();
currentPage.click("feita_" + amanha.getId());
currentPage.navigate("jqibuttonSim");
assertTrue(currentPage.div("tarefa_atrasada_" + atrasada.getId())
.exists());
assertTrue(currentPage.div("tarefa_hoje_" + hoje.getId())
.exists());
assertFalse(currentPage.div("tarefa_prox_" + amanha.getId())
.exists());
}
Refatorei o JavaScript da página!o colega de trabalho que você quer matar agora
public void mostraTarefasDoUsuario() {
Tarefa atrasada = ... // cria a tarefa
Tarefa hoje = ... // cria a tarefa
Tarefa amanha = ... // cria a tarefa
Page currentPage = browser.currentPage();
assertTrue(currentPage.div("tarefa_atrasada_" + atrasada.getId()).exists());
assertTrue(currentPage.div("tarefa_hoje_" + hoje.getId()).exists());
assertTrue(currentPage.div("tarefa_prox_" + amanha.getId()).exists());
}
public void someComTarefaJaPronta() {
Tarefa atrasada = ... // cria a tarefa
Tarefa hoje = ... // cria a tarefa
Tarefa amanha = ... // cria a tarefa
Page currentPage = browser.currentPage();
currentPage.click("feita_" + amanha.getId());
currentPage.navigate("jqibuttonSim");
assertTrue(currentPage.div("tarefa_atrasada_" + atrasada.getId()).exists());
assertTrue(currentPage.div("tarefa_hoje_" + hoje.getId()).exists());
assertFalse(currentPage.div("tarefa_prox_" + amanha.getId()).exists());
}
Copiou, colou? Isolou!
public void mostraTarefasDoUsuario() {
Tarefa atrasada = ... // cria a tarefa
Tarefa hoje = ... // cria a tarefa
Tarefa amanha = ... // cria a tarefa
PaginaDeTarefas tarefas = new PaginaDeTarefas(browser);
assertTrue(tarefas.mostrouTarefaAtrasada(atrasada));
assertTrue(tarefas.mostrouTarefaHoje(hoje));
assertTrue(tarefas.mostrouProximaTarefa(amanha));
}
Copiou, colou? Isolou!
public class PaginaDeTarefas {
// construtor
public boolean mostrouTarefaAtrasada(Tarefa atrasada) {
return currentPage.div("tarefa_atrasada_" + atrasada.getId()).exists();
}
public boolean mostrouTarefaHoje(Tarefa hoje) {
return currentPage.div("tarefa_hoje_" + hoje.getId()).exists();
}
public boolean mostrouProximaTarefa(Tarefa amanha) {
return currentPage.div("tarefa_prox_" + amanha.getId()).exists();
}
}
Page Object
public void mostraTarefasDoUsuario() {
Tarefa atrasada = ... // cria a tarefa
Tarefa hoje = ... // cria a tarefa
Tarefa amanha = ... // cria a tarefa
PaginaDeTarefas tarefas = new PaginaDeTarefas(browser);
assertTrue(tarefas.mostrouTarefaAtrasada(atrasada));
assertTrue(tarefas.mostrouTarefaHoje(hoje));
assertTrue(tarefas.mostrouProximaTarefa(amanha));
}
public void mostraTarefasDoUsuario() {
Calendar ontem = Calendar.getInstance();
ontem.roll(Calendar.DAY_OF_MONTH, -1);
Calendar hoje = Calendar.getInstance();
Calendar amanha = Calendar.getInstance();
amanha.roll(Calendar.DAY_OF_MONTH, 1);
Tarefa atrasada = new Tarefa(usuario, ontem, new Categoria(), "Acabar palestra");
Tarefa hoje = new Tarefa(usuario, hoje, new Categoria(), "Apresentar palestra");
Tarefa amanha = new Tarefa(usuario, amanha, new Categoria(), "Descansar");
// ...
}
Hmmm... :/
public void testeSemMocks() {
Produtos p = new Produtos(
new Item(new Categoria(), new Valor()),
new Item(new Categoria(), new Valor()));
// ...
}
public void testeSemMocks() {
Produtos p = new Produtos(criaItem(), criaItem());
// ...
}
private Item criaItem() {
return new Item(new Categoria(), new Valor());
}
public void testeSemMocks() {
ItemBuilder itens = new ItemBuilder();
Produtos p = new Produtos(itens.cria(), itens.cria());
// ...
}
public void testeSemMocks() {
Builder builder = new Builder();
Produtos p = new Produtos(builder.umItem().comValor(15.00).cria(),
builder.umItem().comValor(15.00).cria());
// ...
}
public void mostraTarefasDoUsuario() {
Calendar ontem = Calendar.getInstance();
ontem.roll(Calendar.DAY_OF_MONTH, -1);
Calendar hoje = Calendar.getInstance();
Calendar amanha = Calendar.getInstance();
amanha.roll(Calendar.DAY_OF_MONTH, 1);
Tarefa atrasada = new Tarefa(usuario, ontem, new Categoria(), "Acabar palestra");
Tarefa hoje = new Tarefa(usuario, hoje, new Categoria(), "Apresentar palestra");
Tarefa amanha = new Tarefa(usuario, amanha, new Categoria(), "Descansar");
// ...
}
public void mostraTarefasDoUsuario() {
Tarefa atrasada = mother.umaTarefa()
.para(mother.ontem())
.comDescricao("Terminar palestra")
.build();
Tarefa hoje = mother.umaTarefa()
.para(mother.hoje())
.comDescricao("Apresentar palestra")
.build();
Tarefa amanha = mother.umaTarefa()
.para(mother.amanha())
.comDescricao("Descansar")
.build();
// ...
}
public class TarefaBuilder {
private Tarefa tarefa;
public TarefaBuilder(ObjectMother mother) {
this.mother = mother;
this.tarefa = defaults();
}
private Tarefa defaults() {
return new Tarefa(mother.umUsuario().build(),
mother.hoje(),
mother.umaCategoria().build(),
"");
}
public TarefaBuilder para(Calendar dia) {
tarefa.setPrazo(dia);
return this;
}
public TarefaBuilder comDescricao(String descricao) {
tarefa.setDescricao(descricao);
return this;
}
public Tarefa build() {
return tarefa;
}
}
public void canProvideCustomRequestScopedComponents() {
checkAvailabilityFor(false,
Arrays.<Class<?>>asList(MyRequestComponent.class));
}
Fundamental para TDD!
public void class_is_public_not_final_with_one_protected_constructor() {
Class cls = DateTimeUtils.class;
assertTrue(isPublic(cls));
assertFalse(isFinal(cls)));
assertTrue(hasOnlyConstructors(cls, protectedConstructor));
DateTimeUtils utils = new DateTimeUtils() {};
}
public void class_is_public_not_final_with_one_protected_constructor() {
Class cls = DateTimeUtils.class;
assertTrue("Class is public", isPublic(cls));
assertFalse("Class is not final", isFinal(cls)));
assertTrue("Class has only one constructor and it's protected",
hasOnlyConstructors(cls, protectedConstructor));
DateTimeUtils utils = new DateTimeUtils() {};
}
public void class_is_public_not_final_with_one_protected_constructor() {
Class cls = DateTimeUtils.class;
assertTrue("Class is public", isPublic(cls));
assertFalse("Class is not final", isFinal(cls)));
assertTrue("Class has only one constructor and it's protected",
hasOnlyConstructors(cls, protectedConstructor));
DateTimeUtils utils = new DateTimeUtils() {};
}
Redundância :/
isPublic
, isFinal
: onde colocar?
public void class_is_public_not_final_with_one_protected_constructor() {
Class cls = DateTimeUtils.class;
assertThat(cls, MyMatchers.isPublic());
assertThat(cls, Matchers.not(MyMatchers.isFinal()));
assertThat(cls.getDeclaredConstructors(),
Matchers.arrayContaining(MyMatchers.protectedConstructor()));
DateTimeUtils utils = new DateTimeUtils() {};
}
public class MyMatchers {
public static Matcher<Class> isPublic() {
return new TypeSafeMatcher<Class>() {
public boolean matchesSafely(Class cls) {
return Modifier.isPublic(cls.getModifiers());
}
public void describeTo(Description desc) {
desc.appendText("public class");
}
};
}
}
public void cool_asserts() {
assertThat(true, is(true));
assertThat(123, equalTo(123));
assertThat("important", containsString("ant"));
assertThat(Arrays.asList(1, 2, 3), hasItems(2, 3));
assertThat(Arrays.asList(1, 2, 3), not(hasItems(4)));
}
Métodos da classe org.hamcrest.Matchers
assertThat(tarefa, ehPara(mother.ontem()));
public class PrazoDeTarefaMatcher extends TypeSafeMatcher<Tarefa> {
private Calendar prazoEsperado;
public PrazoDeTarefaMatcher(Calendar prazoEsperado) {
this.prazoEsperado = prazoEsperado;
}
public boolean matchesSafely(Tarefa recebida) {
return recebida.getPrazo().equals(this.prazoEsperado);
}
public void describeTo(Description desc) {
desc.appendText("Tarefa para " + this.prazoEsperado);
}
@Factory
public static PrazoDeTarefaMatcher ehPara(Calendar prazo) {
return new PrazoDeTarefaMatcher(prazo);
}
}
←
←
←
Melhorando a legibilidade de seus testes com o Hamcrest
(blog da Caelum)
http://is.gd/2DfDsA
public class ObjectMother {
public TarefaBuilder umaTarefa() {}
public UsuarioBuilder umaTarefa() {}
public ProdutoBuilder umaTarefa() {}
public ClienteBuilder umaTarefa() {}
// 1 para cada entidade ...
}
Trabalho... :(
Factory.define :job do |f|
f.sequence(:title) {|n| "Title#{n}"}
f.sequence(:description) {|n| "Description#{n}" }
f.association :local, :factory => :local
f.association :company, :factory => :company
f.enabled true
f.how_to_apply "by email"
f.terms_accepted true
f.tag_list 'arroz feijao fuba'
end
E depois, para usar:
Factory(:job) # já cria e salva no banco
Factory(:job, :enabled => false) # customiza