1 / 61

xUnit Test Patterns

xUnit Test Patterns. writing good unit tests. Peter Wiles. introduction what makes a good unit test? writing good unit tests signs of bad unit tests designing testable software further reading. the state of agile practices. Management practices. Technical practices.

strom
Télécharger la présentation

xUnit Test Patterns

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. xUnit Test Patterns writing good unit tests Peter Wiles

  2. introduction what makes a good unit test? writing good unit tests signs of bad unit tests designing testable software further reading

  3. the state of agile practices Management practices Technical practices Daily standup – 78% Iteration planning – 74% Release planning – 65% Burndown – 64% Retrospectives – 64% Velocity – 52% Unit testing – 70% Continuous Integration – 54% Automated builds – 53% Coding standards – 51% Refactoring – 48% Test driven development – 38% http://www.versionone.com/state_of_agile_development_survey/11/

  4. “continuous attention to technical excellence and good design enhances agility” http://agilemanifesto.org/principles.html

  5. theory: good unit tests are important.

  6. “legacy code is simply code without tests” - Michael Feathers

  7. no tests = ? agility bad tests = worse agility good tests = good agility you can’t be truly agile without automated tests

  8. tests do not replace good, rigorous software engineering discipline, they enhance it.

  9. what makes a good unit test?

  10. a good unit test runs fast helps us localise problems - Michael Feathers, again

  11. when is a unit test not really a unit test?

  12. “What makes a clean test? Three things. Readability, readability and readability.” - Robert C Martin

  13. good unit tests are FRIENDS

  14. fast lightning fast, as in 50 to 100 per second no IO all in process, in memory

  15. robust withstanding changes in unrelated areas of code isolated

  16. independent not dependant on external factors, including time

  17. examples communicating how to use the class under test readability is key

  18. necessary where removing a test would reduce coverage

  19. deterministic the result is the same every time

  20. specific each test testing one thing

  21. fast robust independent examples necessary deterministic specific

  22. writing good unit tests some advice

  23. use an xUnit framework [TestFixture] publicclassTestCalculator { [Test] publicvoid Sum() { var calculator = newCalculator(); var sum = calculator.Sum(5, 4); Assert.AreEqual(9, sum); } }

  24. write your tests first

  25. standardise test structure [Test] publicvoidAppend_GivenEmptyString_ShouldNotAddToPrintItems() { // Arrange var document = CreatePrintableDocument(); // Act document.Append(""); // Assert Assert.AreEqual(0, document.PrintItems.Count); }

  26. be strict Less than 5 lines for Arrange One line for Act One logical Assert (less than 5 lines)

  27. no teardown bare minimum setup

  28. use project conventions testcase class per class test project per project helpers and bootstrappers

  29. use a test naming convention Method_ShouldXX() Method_GivenXX_ShouldYY() Method_WhenXX_ShouldYY()

  30. use a minimal fresh transient fixture per test

  31. use a minimal fresh transient fixture per test the smallest possible fixture you can get away with using

  32. use a minimal fresh transient fixture per test brand new objects every time, where you can

  33. use a minimal fresh transient fixture per test objects that are chucked after each test, left to the garbage collector

  34. use a minimal fresh transient fixture per test the test should create its own fixture

  35. signs of bad unit tests

  36. conditionals if (result == 5) ...

  37. long test methods [Test] publicvoidTestDeleteFlagsSetContactPerson() { ContactPersonmyContact = newContactPerson(); Assert.IsTrue(myContact.Status.IsNew); // this object is new myContact.DateOfBirth = newDateTime(1980, 01, 20); myContact.FirstName = "Bob"; myContact.Surname = "Smith"; myContact.Save(); //save the object to the DB Assert.IsFalse(myContact.Status.IsNew); // this object is saved and thus no longer // new Assert.IsFalse(myContact.Status.IsDeleted); IPrimaryKey id = myContact.ID; //Save the objectsID so that it can be loaded from the Database Assert.AreEqual(id, myContact.ID); myContact.MarkForDelete(); Assert.IsTrue(myContact.Status.IsDeleted); myContact.Save(); Assert.IsTrue(myContact.Status.IsDeleted); Assert.IsTrue(myContact.Status.IsNew); }

  38. invisible setup [Test] publicvoidTestEncryptedPassword() { Assert.AreEqual(encryptedPassword, encryptedConfig.Password); Assert.AreEqual(encryptedPassword, encryptedConfig.DecryptedPassword); encryptedConfig.SetPrivateKey(rsa.ToXmlString(true)); Assert.AreEqual(password, encryptedConfig.DecryptedPassword); }

  39. huge fixture [TestFixtureSetUp] publicvoidTestFixtureSetup() { SetupDBConnection(); DeleteAllContactPersons(); ClassDef.ClassDefs.Clear(); newCar(); CreateUpdatedContactPersonTestPack(); CreateSaveContactPersonTestPack(); CreateDeletedPersonTestPack(); } [Test] publicvoidTestActivatorCreate() { Activator.CreateInstance(typeof (ContactPerson), true); }

  40. too much information [Test] publicvoidTestDelimitedTableNameWithSpaces() { ClassDef.ClassDefs.Clear(); TestAutoInc.LoadClassDefWithAutoIncrementingID(); TestAutoIncbo = newTestAutoInc(); ClassDef.ClassDefs[typeof (TestAutoInc)].TableName = "test autoinc"; DeleteStatementGenerator gen = newDeleteStatementGenerator(bo, DatabaseConnection.CurrentConnection); varstatementCol = gen.Generate(); ISqlStatement statement = statementCol.First(); StringAssert.Contains("`test autoinc`", statement.Statement.ToString()); }

  41. external dependencies these are probably integration tests

  42. too many asserts [Test] publicvoidTestDeleteFlagsSetContactPerson() { ContactPersonmyContact = newContactPerson(); Assert.IsTrue(myContact.Status.IsNew); // this object is new myContact.DateOfBirth = newDateTime(1980, 01, 20); myContact.FirstName = "Bob"; myContact.Surname = "Smith"; myContact.Save(); //save the object to the DB Assert.IsFalse(myContact.Status.IsNew); // this object is saved and thus no longer // new Assert.IsFalse(myContact.Status.IsDeleted); IPrimaryKey id = myContact.ID; //Save the objectsID so that it can be loaded from the Database Assert.AreEqual(id, myContact.ID); myContact.MarkForDelete(); Assert.IsTrue(myContact.Status.IsDeleted); myContact.Save(); Assert.IsTrue(myContact.Status.IsDeleted); Assert.IsTrue(myContact.Status.IsNew); }

  43. duplication between tests repeated calls to constructors is duplication – refactor this.

  44. test chaining

  45. s….l….o….w t….e….s.…t….s …

  46. no automated build process

  47. debugging

  48. test-only code in production if (testing) { //... } #if TEST //... #endif

  49. randomly failing tests

  50. designing testable software

More Related