O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Best practices for writing first class unit tests

3.226 visualizações

Publicada em

A step by step demonstration of the practices and principles you can use to improve the quality and maintainability of your automated unit tests in .NET.

Publicada em: Tecnologia, Negócios
  • D0WNL0AD FULL ▶ ▶ ▶ ▶ http://1url.pw/lPcYM ◀ ◀ ◀ ◀
       Responder 
    Tem certeza que deseja  Sim  Não
    Insira sua mensagem aqui

Best practices for writing first class unit tests

  1. 1. Writing First Class Unit Tests<br />Best Practices<br />Dennis Doomen | Principal Consultant | Aviva Solutions<br />@ddoomen | www.dennisdoomen.net<br />
  2. 2. Unit tests…<br />Are fast<br />Are automated<br />Are small<br />Run in-memory<br />Unit = Single class…or…<br />Dennis Doomen<br />
  3. 3. Integration tests…<br />Can cross boundaries<br />Are slower<br />Candepend on external resources<br />Dennis Doomen<br />
  4. 4. Otherforms of testing<br />System Testing<br />UsabilityTesting<br />User AcceptanceTesting<br />ATDD<br />Dennis Doomen<br />
  5. 5. My First Attempt…<br />Dennis Doomen<br />
  6. 6.         [TestMethod]        public void FindCustomersTest1()        {            var viewModel = new CustomerManagementViewModel();            string propertyChanged = "";            viewModel.PropertyChanged += (sender, args) => propertyChanged = args.PropertyName;                        viewModel.City = "Washington";            viewModel.MinimumAccountBalance = 10000;            viewModel.Find();            var customers = viewModel.Customers;            Assert.AreEqual(2, customers.Count());            Assert.IsTrue(customers.Any(c => c.Id == 15));            Assert.IsTrue(customers.Any(c => c.Id == 81));                        Assert.AreEqual("Customers", propertyChanged);            viewModel.City = "";            viewModel.MinimumAccountBalance = 0;            propertyChanged = "";            viewModel.Find();            Assert.AreEqual(102, viewModel.Customers.Count());        }<br />IntentionRevealing<br />Small andfocused<br />Clearcauseand effect<br />Test onecondition<br />Independent<br />Repeatable<br />No side-effects<br />
  7. 7. If it is not important for the test, it is very important not to show it…<br />My first attempt…<br />
  8. 8. A small improvement…<br />  [TestMethod]        public void When_searching_it_should_account_for_the_city_and_minimal_account_balance()        {<br /> }<br />My first attempt…<br />
  9. 9. My first attempt…<br />More improvements…<br />Isolate The Ugly Stuff<br />UseDependencyInjection<br />
  10. 10.        [TestMethod]        public void When_searching_it_should_account_for_the_city_and_minimal_account_balance()        {            var  dummyCustomers  = new[] { new Customer(), new Customer()};            var service = new ServiceAgentStub();            service.AddDummyCustomers(dummyCustomers);            var viewModel = new CustomerManagementViewModel(service)            {                City = "Washington",                MinimumAccountBalance = 10000            };            string propertyChanged = null;            viewModel.PropertyChanged += (sender, args) => propertyChanged = args.PropertyName;            viewModel.Find();            Assert.AreEqual(2, viewModel.Customers.Count());                        CollectionAssert.AreEquivalent(viewModel.Customers.ToArray(), dummyCustomers);            Assert.AreEqual("Washington", service.City);            Assert.AreEqual(10000, service.MinimumAccountBalance);            Assert.AreEqual("Customers", propertyChanged);        }<br />
  11. 11.     public class ServiceAgentStub : IServiceAgent    {        private List<Customer> dummyCustomers = new List<Customer>();        public decimal? MinimumAccountBalance { get; set; }        public string City { get; set; }        public void AddDummyCustomers(params Customer[] customers)        {            dummyCustomers.AddRange(customers);        }        public IEnumerable<Customer> FindCustomers(string city, decimal? minimumAccountBalance)        {            City = city;            MinimumAccountBalance = minimumAccountBalance;            return dummyCustomers;        }    }<br />
  12. 12. My first attempt…<br />Some more intentions…<br />
  13. 13.        [TestMethod]        public void When_searching_it_should_account_for_the_city_and_minimal_account_balance()        {            var  dummyCustomers  = new[] { new Customer(), new Customer()};            var service = new ServiceAgentStub();            service.AddDummyCustomers(customer1, customer2);<br />       [TestMethod]        public void When_searching_it_should_account_for_the_city_and_minimal_account_balance()        { <br />           var someCustomer = new CustomerBuilder().Build();            var someOtherCustomer = new CustomerBuilder().Build();            var theServiceAgent = new ServiceAgentStub();            theServiceAgent.AddDummyCustomers(someCustomer, someOtherCustomer);<br />
  14. 14.     public class CustomerBuilder : TestDataBuilder<Customer>    {        private static long nextId = 1;        private string city = "Redmond";        private decimal accountBalance = 100;        protected override Customer OnBuild()        {            return new Customer            {                Id = nextId++,                City = city,                AccountBalance = accountBalance            };        }        public CustomerBuilder InCity(string city)        {            this.city = city;            return this;        }        public CustomerBuilder WithAccountBalance(decimal accountBalance)        {            this.accountBalance = accountBalance;            return this;        }    }<br />
  15. 15. My first attempt…<br />Arrange…act…assert…<br />
  16. 16. My first attempt…<br />State versus interaction<br />
  17. 17. My first attempt…<br />Rules toease unit testing…<br />Test small beforeyou test big<br />Prefer state-basedtesting<br />Keep out of the debugger hell<br />
  18. 18.             //-------------------------------------------------------------------------------------------------------------------            // Assert            //-------------------------------------------------------------------------------------------------------------------            Assert.AreEqual(2, viewModel.Customers.Count());                        var expectedCustomers = new[] { someCustomer, someOtherCustomer};            CollectionAssert.AreEquivalent(viewModel.Customers.ToArray(), expectedCustomers);            Assert.AreEqual("Washington", theServiceAgent.City);            Assert.AreEqual(10000, theServiceAgent.MinimumAccountBalance);            Assert.AreEqual("Customers", changedPropertyName);<br />            //-------------------------------------------------------------------------------------------------------------------            // Assert            //-------------------------------------------------------------------------------------------------------------------            viewModel.Customers.Should().Equal(someCustomers);            theServiceAgent.City.Should().Be("Washington");            theServiceAgent.MinimumAccountBalance.Should().Be(10000m);            changedPropertyName.Should().Be("Customers");<br />
  19. 19. My first attempt…<br />AAA versus BDD-style<br />
  20. 20. Andnowforsomefaking…<br />
  21. 21. Karl Seguin wrote:<br />Refusing<br />Getting too excited<br />Testing everything!<br />Integration testing<br />Discover mocking<br />Mocking everything<br />Becoming effective<br />28 May 2009<br />Dennis Doomen<br />
  22. 22. Background InformationJeremy’sLaws of TDD, Test Data Builder, Applying Domain Driven Design (Jimmy Nillson), xUnitPatterns<br />Example Code, FrameworksSilverlightCookbook, Fake It Easy, FluentAssertions<br />
  23. 23. Emaildennis.doomen@avivasolutions.nl<br />Twitter<br />@ddoomen<br />Blogwww.dennisdoomen.net<br />

×