進行状況の追跡を始めよう
Trailhead のホーム
Trailhead のホーム

Write Positive Tests

Learning Objectives

After completing this unit, you’ll be able to:

  • Explain why positive tests are important.
  • Write positive unit tests.

Positive unit tests are tests that return expected results when you present valid data to the tested code. Think of a the classic calculator. A positive test for an addition method might execute with data points 2 and 3 while asserting the output is 5. This is a simplistic example, of course, but the idea is the same. When you execute it with valid data, the code you’re testing should respond with predictable results. 

This video offers insight into the why and how of positive unit tests.


The Pattern

Writing positive unit tests is all about seeing a set of expected results when you know your input data is good. The standard model for positive tests uses the following steps.   Positive testing pattern 

  1. Generate or load test data.
    • Use a data factory or a CSV file.
    • Make assertions to validate your data.
  2. Call Test.StartTest().
    • This resets governor limits and isolates your test from test setup.
  3. Execute the code you’re testing.
  4. Call Test.StopTest().
    • This forces any asynchronous code to complete.
  5. Make assertions about the output of your tested code. You might assert a record exists, or that a field is set to an expected value.

To illustrate these steps, we can look at the AccountWrapper class in the Developer Console. You installed this class with the package you installed in unit 1. AccountWrapper class is a custom logic layer around the Account object. This is a fairly common way to add custom logic to standard objects. In this case, you’re adding some account-level logic to calculate a rounded average amount of opportunities associated with a given account. 

Let’s look at the AccountWrapper class and write some positive tests for it.

  1. Click Setup icon  and select Developer Console.
  2. Select File > Open > AccountWrapper.apxc. This is the code you’re testing.
  3. Select File > New > Apex Class and name the new class AccountWrapper_Tests.
  4. Replace the default contents with the following code.
    @isTest
    private class AccountWrapper_Tests {
      @testSetup
      static void loadTestData(){
        List<Account> accounts = (List<Account>) Test.loadData(Account.SObjectType, 'accountData');
        List<Opportunity> opps = new List<Opportunity>();
        for(Account a : accounts){
          opps.addAll(TestFactory.generateOppsForAccount(a.id, 1000.00, 5));
        }
        insert opps;
      }
      @isTest static void testPositiveRoundedAveragePrice() {
        List<AccountWrapper> accounts = new List<AccountWrapper>();
        for(Account a : [SELECT ID, Name FROM ACCOUNT]){
          accounts.add(new AccountWrapper(a));
        }
        // sanity check asserting that we have opportunities before executing our tested method.
        List<Opportunity> sanityCheckListOfOpps = [SELECT ID FROM Opportunity];
        System.assert(sanityCheckListOfOpps.size() > 0, 'You need an opportunity to continue');
        Test.startTest();
        for(AccountWrapper a : accounts){
          System.assertEquals(a.getRoundedAvgPriceOfOpps(), 1000.00, 'Expected to get 1000.00');
        }
        Test.stopTest();
      }
    }
  5. Click File > Save, then Test > New Run.
  6. Select AccountWrapper_Tests, then select testPositiveRoundedAveragePrice.
  7. Click Run.

Code Highlights

As in the last unit, this test class uses an @TestSetup method that loads the accountData.csv file. It also calls a factory method to generate five opportunities for each of your accounts. 

With accounts and opportunities, you can test the logic of your accountWrappers getRoundedAvgPriceOfOpps() method. This method is designed to return the average price of all opportunities related to this account, rounded to the nearest thousand dollars. Because this is a positive test, the data you loaded and the opportunities you generated are logically consistent with what the method needs. In other words, your opportunities have positive amount values and an easily predictable rounded average. A good maxim for positive testing is: Good code produces expected results when you give it good inputs.

A Note on test.startTest()

Part of what makes the Salesforce platform so great are the governor limits we’ve built into it. These governor limits prevent any one user or org from using all the system resources. The limits ensure, for instance, that Apex code has only 10 seconds to execute. 

Because these limits apply even to unit test execution, they can become difficult. If, for example, you need to insert and query a lot of records while setting up your test, you could hit a governor limit when you actually call the code being tested. That can lead to a false-failure, where your test fails, but not because your code is wrong. 

Using the test.startTest() and test.stopTest() methods lets you tell the platform when you’re calling the code being tested. Functionally, this isolates your tested code by resetting governor limits from the startTest() call until the stopTest() call. For more information on governor limits, check out the link in the Resources section.

Resources