// This helper method starts with just a single parameter: Company company = newCompany(PUBLIC);
// But soon it acquires more and more parameters. // Conditionals creep into the newCompany() method body to handle the nulls, // and the method calls become hard to read due to the long parameter lists: Company small = newCompany(2, 2, null, PUBLIC); Company privatelyOwned = newCompany(null, null, null, PRIVATE); Company bankrupt = newCompany(null, null, PAST_DATE, PUBLIC); // Or a new method is added each time a test needs a different combination of fields: Company small = newCompanyWithEmployeesAndBoardMembers(2, 2, PUBLIC); Company privatelyOwned = newCompanyWithType(PRIVATE); Company bankrupt = newCompanyWithBankruptcyDate(PAST_DATE, PUBLIC);
Company small = newCompany().setEmployees(2).setBoardMembers(2).build(); Company privatelyOwned = newCompany().setType(PRIVATE).build(); Company bankrupt = newCompany().setBankruptcyDate(PAST_DATE).build(); Company arbitraryCompany = newCompany().build();
// Zero parameters makes this method reusable for different variations of Company. // It also doesn’t need conditionals to ignore parameters that aren’t set (e.g. null // values) since a test can simply not set a field if it doesn’t care about it. private static Company.Builder newCompany() { return Company.newBuilder().setType(PUBLIC).setEmployees(100); // Set required fields }
// This test needs a public company, so explicitly set it. // It also needs a company with no board members, so explicitly clear it. Company publicNoBoardMembers = newCompany().setType(PUBLIC).clearBoardMembers().build();
@Test public void addPermissionToDatabase() { new UserAuthorizer(mockUserService, mockPermissionDb).grantPermission(USER, READ_ACCESS);
// The test will fail if any of these methods is not called. verify(mockUserService).isUserActive(USER); verify(mockPermissionDb).getPermissions(USER); verify(mockPermissionDb).isValidPermission(READ_ACCESS); verify(mockPermissionDb).addPermission(USER, READ_ACCESS); }
// Verify only the state-changing method. verify(mockPermissionDb).addPermission(USER, READ_ACCESS); }
vector<pair<int, int>> polygon = ... pair<pair<int, int>, pair<int, int>> bounding_box = GetBoundingBox(polygon); int area = (bounding_box.second.first - bounding_box.first.first) * (bounding_box.second.second - bounding_box.first.second);
pair
first
second
Polygon polygon = ... int area = polygon.GetBoundingBox().GetArea();
map<UserId, string> id_to_name; map<UserId, int> id_to_age;
map<UserId, Person> id_to_person;
person_data[kName] = "Foo";
person.SetName("Foo");
Date
GetMonth
string date = "01-02-03";
Date date(Month::Feb, Day(1), Year(2003));
int timeout_secs = 5;
Duration timeout = Seconds(5);
// Bad, the type tells us what these variables are: String nameString; List<datetime> holidayDateList; // Better: String name; List<datetime> holidays;
// Overly specific names are hard to read: Monster finalBattleMostDangerousBossMonster; Payments nonTypicalMonthlyPayments; // Better, if there's no other monsters or payments that need disambiguation: Monster boss; Payments payments;
// Bad, repeating the context: class AnnualHolidaySale {int annualSaleRebate; boolean promoteHolidaySale() {...}} // Better: class AnnualHolidaySale {int rebate; boolean promote() {...}}
Add Frobber to the list of available widgets. This allows consumers to easily discover the new Frobber widget and add it to their application.