Skip to main content

Prepare to Build Your Apex Tests

Learning Objectives

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

  • Explain the Apex test syntax.
  • Run tests in VS Code on your org.
  • Describe the benefits of using a test data factory.

Before We Start

This badge is part of a series on Apex unit testing consisting of the following badges.

The content in each badge builds on each other, so make sure to take the badges in order.

You’ll also need to install Visual Studio Code and complete the Quick Start: Visual Studio Code for Salesforce Development badge in order to complete the hands-on challenges in this badge.

Prepare to Test

In the Apex Testing: Review Testing Fundamentals badge you learned what testing is and why it’s important. In this badge, you take things a step further and will start preparing your code for testing. Before you do that, though, let’s talk about the syntax used for unit testing in Apex.

Get to Know the Test Method Syntax

Test methods are defined using the @IsTest annotation and have the following syntax:

@IsTest
static void testMethodName() {
  // code_block
}

The @IsTest annotation takes multiple modifiers within parentheses and separated by blanks.

The visibility of a test method doesn’t matter, so declaring a test method as public or private doesn’t make a difference as the testing framework is always able to access test methods. For this reason, the access modifiers are omitted in the syntax.

Test methods must be defined in test classes, which are classes annotated with @IsTest.

Here’s a sample class that shows a definition of a test class with one test method.

@IsTest
private class MyTestClass {
  @IsTest
  static void testMyTestMethod() {
    // code_block
    // GIVEN
    // Part where you create the test data needed for testing your method
    // WHEN
    Test.startTest();
      // Where you call the method being tested
    Test.stopTest();
    // THEN
    // Where you place your assertions - so you can trust the results
  }
}

Test classes can be either private or public. If you’re using a test class for unit testing only, declare it as private. Public test classes are typically used for test data factory classes, which are covered in the next unit.

Install VS Code and Connect to Your Trailhead Playground

To execute the tests that you’ll write in this module, you’ll use VS Code. Complete Quick Start: Visual Studio Code for Salesforce Development to learn how to install it, create a project, and connect the project to your Trailhead playground. You’ll use the VSCodeQuickstart project and VS Code to complete this badge.

Test the TemperatureConverter Class

The following example is of a test class with three test methods. The class method that’s being tested takes a temperature in Fahrenheit as an input. It converts this temperature to Celsius and returns the converted result. Let’s add the custom class and its test class.

  1. Open the VSCodeQuickstart project in VS Code.
  2. In the Explorer sidebar, right-click the folder classes, then choose SFDX: Create Apex Class.
  3. Enter TemperatureConverter for the name and accept the default directory.
  4. Replace the contents of the class with the following code.
    public with sharing class TemperatureConverter {
      // Takes a Fahrenheit temperature and returns the Celsius equivalent.
      public static Decimal fahrenheitToCelsius(Decimal fahrenheit) {
        Decimal celsius = (fahrenheit - 32) * 5/9;
        return celsius.setScale(2);
      }
    }
  5. Click File | Save.
  6. Repeat the previous steps to create the TemperatureConverterTests class. Add the following for this class.
    @IsTest
    private class TemperatureConverterTests {
      @IsTest
      static void testWarmTemp() {
        //GIVEN
        Decimal initialTemp = 70;
        //WHEN
        Test.startTest();
          Decimal celsius = TemperatureConverter.fahrenheitToCelsius(initialTemp);
        Test.stopTest();
        //THEN
        Assert.areEqual(21.11,celsius);
      }
      @IsTest
      static void testFreezingPoint() {
        //GIVEN
        Decimal initialTemp = 32;
        //WHEN
        Test.startTest();
          Decimal celsius = TemperatureConverter.FahrenheitToCelsius(initialTemp);
        Test.stopTest();
        //THEN
        Assert.areEqual(0,celsius);
      }
      @IsTest
      static void testBoilingPoint() {
        //GIVEN
        Decimal initialTemp = 212;
        //WHEN
        Test.startTest();
          Decimal celsius = TemperatureConverter.FahrenheitToCelsius(initialTemp);
        Test.stopTest();
        //THEN
        Assert.areEqual(100,celsius,'Boiling point temperature is not expected.');
      }
      @IsTest
      static void testNegativeTemp() {
        //GIVEN
        Decimal initialTemp = -10;
        //WHEN
        Test.startTest();
          Decimal celsius = TemperatureConverter.FahrenheitToCelsius(initialTemp);
        Test.stopTest();
        //THEN
        Assert.areEqual(-23.33,celsius);
      }
    }
  7. Save the file.
  8. Right-click the files you’re working on, then choose SFDX: Deploy Source To Org.

The TemperatureConverterTests test class verifies that the method works as expected by calling it with different inputs for the temperature in Fahrenheit. Each test method verifies one type of input: a warm temperature, the freezing point temperature, the boiling point temperature, and a negative temperature.

The verifications are done by calling the Assert.areEqual method, which takes two parameters: the first is the expected value, and the second is the actual value. There is another version of this method that takes a third parameter—a string that describes the comparison being done, which is used in testBoilingPoint. This optional string is logged if the assertion fails.

Note

You can retrieve code coverage results in VS Code for your Apex classes and Apex triggers every time you run one or more tests. To do this, edit your user or workspace settings, search for and check retrieve-test-code-coverage and then run your Apex tests. You can now see the code coverage in the Output panel, which shows the coverage percentage per Apex class and Apex trigger and lines that were not covered by the test run results.

Let’s run the test methods in this class.

  1. Click the Run All Tests button that appears on the TemperatureConverterTests class.

While one test method would have resulted in full coverage of the TemperatureConverter class, it’s still important to test for different inputs to ensure the quality of your code. Obviously, it isn’t possible to verify every data point, but you can test for common data points and different ranges of input. For example, you can verify passing positive and negative numbers, boundary values, and invalid parameter values to verify negative behavior. The tests for the TemperatureConverter class verify common data points, like the boiling temperature, and negative temperatures.

The TemperatureConverterTests test class doesn’t cover invalid inputs or boundary conditions. Boundary conditions are about minimum and maximum values. In this case, the temperature conversion method accepts a Decimal, which can accept large numbers, higher than Double values. For invalid inputs, there is no invalid temperature, but the only invalid input is null. How does the conversion method handle this value? In this case, when the Apex runtime dereferences the parameter variable to evaluate the formula, it throws a System.NullPointerException. You can modify the FahrenheitToCelsius method to check for an invalid input and return null in that case, and then add a test to verify the invalid input behavior.

Simulate a Failure

Up to this point, all tests pass because the conversion formula used in the class method is correct. But that’s boring! Let’s try to simulate a failure just to see what happens when an assertion fails. For example, let’s modify the boiling point temperature test and pass in a false expected value for the boiling point Celsius temperature (0 instead of 100). This causes the corresponding test method to fail.

  1. Change the testBoilingPoint test method to the following.
    @IsTest
    static void testBoilingPoint() {
      //GIVEN
      // Temperature is set to 212 degrees
      //WHEN
      Test.startTest();
        Decimal celsius = TemperatureConverter.FahrenheitToCelsius(212);
      Test.stopTest();
      //THEN
      // Simulate failure
      Assert.areEqual(0,celsius,'Boiling point temperature is not expected.');
    }
  2. Save and deploy the file to your org.
  3. Click the Run Test button that appears on the testBoilingPoint method.
    The assertion in testBoilingPoint fails and throws a fatal error (an AssertException that can’t be caught).

You’ll see the text following Assertion Failed: is the text we provided in the Assert.areEqual statement.

System.AssertException: Assertion Failed: Boiling point temperature is not expected.: Expected: 0, Actual: 100.00

The test data in these test methods are numbers and not Salesforce records. Find out more about how to test Salesforce records and how to set up your data in the next unit.

Resources

Share your Trailhead feedback over on Salesforce Help.

We'd love to hear about your experience with Trailhead - you can now access the new feedback form anytime from the Salesforce Help site.

Learn More Continue to Share Feedback