Archive for the ‘Testes Automatizados’ tag
(Inglês) Model validation specifications
Este texto está disponível apenas em Inglês.
(Inglês) Thoughts on software testing
Este texto está disponível apenas em Inglês.
Testando a engine de blog com BDD
Continuando o projeto de uma engine de Blog, resolvi dar início ao plano de testes unitários.
Optei por utilizar a abordagem Behavior Driven Development, o que alguns chamam de uma evolução do TDD.
O interessante desta abordagem é que o código da base de testes fica limpo, focado nas regras de negócio.
Quando algum teste falhar, dificilmente o programador perderá tempo entendendo porque o teste parou de funcionar e o quê precisa ser consertado.
Para ajudar a testar os objetos de maneira desacoplada, resolvi adotar o framework Rhino Mocks.
Para aplicar o BDD utilizei o NBehave, que neste caso está apoiado sobre o NUnit.
Ainda estou estudando como implentar mocks de maneira adequada e também amadurecendo a utilização das técnicas de BDD.
Mas gostei bastante do resultado.
using NBehave.Narrator.Framework;
using NBehave.Spec.NUnit;
using NUnit.Framework;
using Rhino.Mocks;
using Specification = NUnit.Framework.TestAttribute;
namespace MyCompany.Web.Blog.Tests
{
[TestFixture]
public class Author_publishing_entries : SpecBase
{
private IBlogContext context;
private Entry entry;
private Story story;
private MockRepository mocks;
[Story]
public override void MainSetup()
{
base.MainSetup();
PrepareContext();
story = new Story("Publishing");
story.AsA("blog author")
.IWant("to be able to publish an entry")
.SoThat("it can be shared with a reader");
}
private void PrepareContext()
{
entry = new Entry("someTitle", "someSlug", "someIntro",
"someContent", null);
mocks = new MockRepository();
context = mocks.StrictMock<IBlogContext>();
var blog = mocks.Stub<IBlog>();
var author = mocks.PartialMock<Author>();
author.Blogging = blog;
Rhino.Mocks.SetupResult.For(context.GetBlog())
.Return(blog);
Rhino.Mocks.SetupResult.For(context.CurrentAuthor())
.Return(author);
mocks.ReplayAll();
}
[Specification]
public void Attempting_to_publish()
{
var blog = context.GetBlog();
var author = context.CurrentAuthor();
story.WithScenario("publishing an entry")
.Given("the blog under use", () => blog.ShouldNotBeNull())
.And("the author is blogging", () => author.ShouldNotBeNull())
.When("he attempts to publish an entry", () => author.Publish(entry))
.Then("the blog engine is comunicated", () =>
blog.AssertWasCalled(b => b.SubmitEntry(entry)));
}
}
}
p>
using System.Collections.Generic;
using NBehave.Narrator.Framework;
using NBehave.Spec.NUnit;
using NUnit.Framework;
using Rhino.Mocks;
using MyCompany.Web.Blog.Specifications;
using Specification = NUnit.Framework.TestAttribute;
namespace MyCompany.Web.Blog.Tests
{
[TestFixture]
public class Blog_receiving_entries : SpecBase
{
private IBlogContext context;
private Entry validEntry;
private Entry entryWithInvalidTitle;
private Entry entryWithInvalidSlug;
private Entry entryWithInvalidContent;
private List<Entry> invalidEntries;
private Story story;
private MockRepository mocks;
[Story]
public override void MainSetup()
{
base.MainSetup();
PrepareContext();
story = new Story("Receiving entries");
story.AsA("Blog engine")
.IWant("to receive entries")
.SoThat("I can show them to a reader");
}
private void PrepareContext()
{
const string validTitle = "validTitle",
validSlug = "validSlug", validContent = "validContent";
const string intro = "intro";
const List<Tag> tagsRelated = null;
const string invalidTitle = "",
invalidSlug = "", invalidContent = "";
validEntry = new Entry(validTitle, validSlug,
intro, validContent, tagsRelated);
entryWithInvalidTitle = new Entry(invalidTitle,
validSlug, intro, validContent, tagsRelated);
entryWithInvalidSlug = new Entry(validTitle,
invalidSlug, intro, validContent, tagsRelated);
entryWithInvalidContent = new Entry(validTitle,
validSlug, intro, invalidContent, tagsRelated);
invalidEntries = new List<Entry>();
invalidEntries.AddRange(new Entry[]
{
entryWithInvalidTitle,
entryWithInvalidSlug,
entryWithInvalidContent
});
mocks = new MockRepository();
context = mocks.StrictMock<IBlogContext>();
var blog = mocks.PartialMock<Blog>();
var repository = mocks.Stub<IBlogRepository>();
blog.Repository = repository;
Rhino.Mocks.SetupResult.For(context.GetBlog())
.Return(blog);
mocks.ReplayAll();
}
[Specification]
public void Receiving_valid_entries()
{
var blog = context.GetBlog();
story.WithScenario("receiving a valid entry")
.Given("the blog under use", () =>
blog.ShouldNotBeNull())
.When("it receives a valid entry", () =>
blog.SubmitEntry(validEntry))
.Then("the entry is accepted", () =>
blog.Entries.Contains(validEntry).ShouldBeTrue());
}
[Specification]
public void Receiving_invalid_entries()
{
var blog = context.GetBlog();
story.WithScenario("receiving an invalid entry")
.Given("the blog under use", () =>
blog.ShouldNotBeNull())
.When("it receives an invalid entry", () => { })
.Then("the entry is rejected", () =>
invalidEntries.ForEach(invalidEntry =>
typeof(BlogException).ShouldBeThrownBy(() =>
blog.SubmitEntry(invalidEntry))));
}
}
}