rafanoronha.speaking()

software development stuff

Archive for the ‘Testes Automatizados’ tag

(Inglês) Model validation specifications

without comments

Este texto está disponível apenas em Inglês.

Written by rafanoronha

June 8th, 2009 at 8:56 pm

(Inglês) Thoughts on software testing

with 2 comments

Este texto está disponível apenas em Inglês.

Written by rafanoronha

May 20th, 2009 at 6:08 pm

Posted in Sem categoria

Tagged with

Testando a engine de blog com BDD

without comments

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))));
        }
    }
}

Written by rafanoronha

February 28th, 2009 at 11:26 pm