Skip to main content
A Trailblazer Community no Slack está agora em beta aberto. Participe e interaja em tempo real. Junte-se a nós no Slack

Introdução aos testes de unidade do Apex

Objetivos de aprendizagem

Após concluir esta unidade, você estará apto a:

  • Descrever os principais benefícios dos testes de unidade do Apex.
  • Definir uma classe com métodos de teste.
  • Executar todos os métodos de teste de uma classe e inspecionar falhas.
  • Criar e executar um conjunto de classes de teste.
Nota

Nota

Deseja aprender em português (Brasil)? Comece o desafio em um Trailhead Playground de português (Brasil) e use as traduções fornecidas entre parênteses para navegar. Copie e cole somente os valores em inglês porque as validações dos desafios dependem de dados em inglês. Se você não passar no desafio em sua organização de português (Brasil), recomendamos que (1) mude o local para os Estados Unidos, (2) mude o idioma para inglês, seguindo as instruções aqui, e (3) clique novamente no botão “Validar o desafio”.

Consulte o emblema Trailhead no seu idioma para saber mais sobre como aproveitar a experiência de Trailhead em outros idiomas.

Testes de unidade do Apex

A estrutura de testes do Apex permite que você escreva e execute testes para suas classes e acionadores do Apex. Os testes de unidade do Apex garantem alta qualidade para seu código do Apex e lhe permitem cumprir os requisitos para implantação do Apex.

O teste é o segredo do desenvolvimento bem-sucedido em longo prazo e um componente essencial do processo de desenvolvimento. Com a estrutura de testes do Apex é mais fácil testar seu código do Apex. O código do Apex só pode ser escrito em uma sandbox ou em uma organização do desenvolvedor, e não em uma organização de produção. O código do Apex pode ser implantado em uma organização de produção a partir de um sandbox. Além disso, os desenvolvedores de aplicativos podem distribuir o código do Apex aos clientes de suas organizações de desenvolvedores carregando os pacotes para o Salesforce AgentExchange. Além de serem fundamentais para a garantia de qualidade, os testes de unidade do Apex também são requisitos para implantar e distribuir o Apex.

Os testes de unidade do Apex resultam em códigos aprimorados. A estrutura de testes do Apex:

  • Garante que suas classes e acionadores do Apex funcionem conforme previsto.
  • Tem um conjunto de testes de regressão que pode ser executado novamente sempre que as classes e os acionadores forem atualizados a fim de garantir que as futuras atualizações que você vier a fazer ao seu aplicativo não interrompam a funcionalidade existente.
  • Cumpre os requisitos de cobertura de código para a implantação do Apex na produção ou distribuição do Apex a clientes por meio de pacotes.
  • Oferece aplicativos de alta qualidade à organização de produção, o que torna os usuários de produção mais produtivos.
  • Oferece aplicativos de alta qualidade aos assinantes de pacotes, o que aumenta a confiança de seus clientes.

Requisito de cobertura de código para implantação

Antes de implantar seu código ou empacotá-lo no Salesforce AgentExchange, pelo menos 75% do código do Apex deve ser coberto por testes e todos esses testes devem ser aprovados. Além disso, cada acionador deve ter uma cobertura. Embora a cobertura de código seja um requisito para a implantação, não escreva testes apenas para atender a essa exigência. Teste os casos de uso comuns em seu aplicativo, incluindo casos positivos e negativos do teste, bem como o processamento em massa ou de um só registro.

Classe de teste e sintaxe do método de teste

As classes de teste do Apex com a anotação @IsTest. As classes de teste podem ser definidas como modificadores de acesso privados ou públicos. Se você estiver usando uma classe de teste apenas para testes de unidade, declare-a como privada. As classes de teste públicas geralmente são usadas em classes de fábrica de dados de teste, que abordaremos na unidade Criar dados de teste para testes do Apex. As classes definidas como @IsTest devem ser classes de nível superior.

Na classe de teste, os métodos de teste também são definidos usando a anotação @IsTest. A visibilidade de um método de teste não importa, por isso, declarar um método de teste como público ou privado não faz diferença, pois a estrutura de testes é sempre capaz de acessar métodos de teste. Por essa razão, os modificadores de acesso são omitidos na sintaxe do método.

Este exemplo de código mostra uma definição de uma classe de teste com um método de teste.

@IsTest
private with sharing class MyTestClass {
  @IsTest static void myTest() {
    // code_block
  }
}

A anotação @IsTest pode utilizar vários modificadores entre parênteses e separados por espaços. Abordaremos brevemente a anotação @IsTest(seeAllData=true) na unidade Criar dados de teste para testes do Apex.

Exemplo de teste de unidade: Testar a classe TemperatureConverter

O exemplo simples a seguir pertence a uma classe de teste com três métodos de teste. O método de classe que está sendo testado possui uma temperatura em Fahrenheit como entrada. Ele converte essa temperatura para Celsius e informa o resultado convertido. Vamos adicionar a classe personalizada e sua classe de teste.

  1. Abra o Web Console no menu de acesso rápido (Ícone de engrenagem de Configuração).
  2. No Web Console, pressione Ctrl+Shift+P (Windows) ou ⌘+Shift+P (macOS) para abrir a paleta de comandos.
  3. Insira SFDX: Create Apex Class e pressione Enter.
  4. Para o tipo de modelo, selecione DefaultApexClass e pressione Enter.
  5. Como nome da classe, insira TemperatureConverter e pressione Enter.
  6. Para o diretório de saída, selecione force-app/main/default/classes e pressione Enter.
  7. Substitua o corpo de classe padrão pelo seguinte.
public with sharing class TemperatureConverter {
  // Takes a Fahrenheit temperature and returns the Celsius equivalent.
  public static Decimal FahrenheitToCelsius(Decimal fh) {
    Decimal cs = (fh - 32) * 5/9;
    return cs.setScale(2);
  }
}
  1. Para salvar e implantar sua classe, pressione Ctrl+S (Windows) ou ⌘+S (macOS).
  2. Repita as etapas anteriores para criar a classe TemperatureConverterTest. Substitua o corpo de classe padrão pelo seguinte.
    @IsTest
    private with sharing class TemperatureConverterTest {
      @IsTest static void testWarmTemp() {
        Decimal celsius = TemperatureConverter.FahrenheitToCelsius(70);
        Assert.areEqual(21.11,celsius);
      }
      @IsTest static void testFreezingPoint() {
        Decimal celsius = TemperatureConverter.FahrenheitToCelsius(32);
        Assert.areEqual(0,celsius);
      }
      @IsTest static void testBoilingPoint() {
        Decimal celsius = TemperatureConverter.FahrenheitToCelsius(212);
        Assert.areEqual(100,celsius,'Boiling point temperature is not expected.');
      }
      @IsTest static void testNegativeTemp() {
        Decimal celsius = TemperatureConverter.FahrenheitToCelsius(-10);
        Assert.areEqual(-23.33,celsius);
      }
    }

A classe de teste TemperatureConverterTest verifica se o método funciona conforme previsto, chamando-o com diferentes entradas para a temperatura em Fahrenheit. Cada método de teste verifica um tipo de entrada: uma temperatura quente, a temperatura do ponto de congelamento, a temperatura do ponto de ebulição e uma temperatura negativa. As verificações são feitas chamando o método Assert.areEqual() que recebe dois parâmetros. O primeiro parâmetro é o valor esperado e o segundo é o valor real. Este método também pode aceitar um terceiro parâmetro, que é uma cadeia de caracteres que descreve a comparação que está sendo feita. Este terceiro parâmetro opcional é usado no exemplo testBoilingPoint(). A cadeia de caracteres especificada está registrada caso a declaração falhe.

Habilitar resultados de cobertura de código

Antes de executar testes, habilite o Web Console para recuperar os resultados de cobertura de código.

  1. No Web Console, clique em Ícone de menu na parte superior da barra de atividades.
  2. Selecione File (Arquivo) | Preferences (Preferências) | Settings (Configurações) para abrir a janela Settings (Configurações).
  3. Na caixa de pesquisa, insira retrieve.
  4. Habilite a configuração Salesforcedx-vscode-apex-testing: Retrieve-test-code-coverage.
  5. Feche a janela.

Agora vamos executar os métodos nesta classe de teste.

  1. No Web Console, clique em Ícone de Testing (Testes) na barra de atividades. O painel lateral Testing (Testes) é aberto.
  2. Na barra de pesquisa Testing (Testes), insira TemperatureConverterTest.
  3. Para executar todos os métodos de teste na classe, passe o cursor sobre a linha TemperatureConverterTest e clique em Ícone de Run Test (Executar teste).

No painel Test Results (Resultados dos testes), você vê os resultados dos seus testes. No painel lateral Testing (Testes), os métodos de teste agora exibem marcas de verificação verdes, indicando que todos os testes foram aprovados. O Web Console também gera arquivos JSON e Markdown dos resultados dos testes, localizados no diretório .sfdx/tools/testresults/apex.

Os resultados dos testes para a classe TemperatureConverterTest. O ícone do painel lateral Testing (Testes), os métodos de teste aprovados no painel lateral Testing (Testes), o arquivo Markdown dos resultados dos testes e o painel Test Results (Resultados dos testes) estão destacados.

Depois de executar os testes, a cobertura de código é gerada automaticamente para as classes e acionadores do Apex presentes na organização. Você pode verificar o percentual de cobertura de código no arquivo Markdown dos resultados dos testes. Neste exemplo, a classe TemperatureConverter tem uma cobertura de 100%, conforme mostrado nesta imagem.

O percentual de cobertura de código por classe no Web Console. O arquivo Markdown dos resultados dos testes está destacado.

Note

Sempre que modificar o código do Apex, execute novamente os testes para atualizar os resultados de cobertura de código.

Embora um método de teste teria resultado em uma cobertura total da classe TemperatureConverter, ainda é importante testar diferentes entradas para garantir a qualidade do seu código. Obviamente, não é possível verificar todos os pontos de dados, mas você pode realizar testes em pontos de dados comuns e diferentes intervalos de entrada. Por exemplo, você pode verificar a aprovação de números positivos e negativos, valores-limite e valores de parâmetros inválidos para verificar o comportamento negativo. Os testes para a classe TemperatureConverter verificam os pontos de dados comuns, como pontos de congelamento e ebulição, e temperaturas positivas e negativas.

No entanto, a classe de teste TemperatureConverterTest atualmente não abrange condições-limite ou entradas inválidas. As condições-limite são os valores mínimo e máximo que o método é capaz de processar. No caso das entradas inválidas, considere o que ocorre se null for passado como argumento para FahrenheitToCelsius(). Nesse caso, quando o tempo de execução do Apex desreferencia a variável do parâmetro para avaliar a fórmula, ele lança um System.NullPointerException. Para tratar esse erro, você pode modificar o método FahrenheitToCelsius() para verificar se há uma entrada inválida e, nesse caso, retornar null. Em seguida, adicione um método de teste à classe TemperatureConverterTest para verificar o comportamento da entrada inválida.

Até este ponto, todos os testes são aprovados porque a fórmula de conversão utilizada no método de classe é correta. Mas isso é aborrecido! Tentaremos simular uma falha apenas para ver o que acontece quando uma declaração falha. Por exemplo, vamos modificar o teste de temperatura de ponto de ebulição e aprovar um valor falso previsto para a temperatura de ponto de ebulição em graus Celsius (0 em vez de 100). Isso faz com que o método de teste correspondente falhe.

  1. Altere o método de teste testBoilingPoint() para o código a seguir e salve a classe de teste atualizada.
@IsTest
static void testBoilingPoint() {
  Decimal celsius = TemperatureConverter.FahrenheitToCelsius(212);
  // Simulate failure
  Assert.areEqual(0,celsius,'Boiling point temperature is not expected.');
}
  1. No painel lateral Testing (Testes), execute todos os métodos de teste na classe TemperatureConverterTest. A declaração em testBoilingPoint() falha e gera um erro fatal (uma AssertException que não pode ser capturada).
  2. Verifique os resultados no painel Test Results (Resultados dos testes). A execução de teste informa a falha de um em cada quatro testes.
  3. Para obter a mensagem de erro da falha do teste, selecione testBoilingPoint no painel lateral Testing (Testes). A mensagem de erro inclui o texto que fornecemos na instrução Assert.areEqual(): System.AssertException: Assertion Failed: Boiling point temperature is not expected.: Expected: 0, Actual: 100.00 (System.AssertException: Falha na declaração: A temperatura de ponto de ebulição não é esperada.:Esperada: 0, Real: 100.00)

Os novos resultados dos testes para a classe TemperatureConverterTest, em que a asserção no método testBoilingPoint() falha.

Os dados de teste nesses métodos de teste são números e não registros do Salesforce. Na próxima unidade, você aprenderá mais sobre como testar os registros do Salesforce e como configurar seus dados.

Aumente sua cobertura de código

Ao escrever testes, tente alcançar a maior cobertura de código possível. Não basta apontar para uma cobertura de 75%, que é a menor cobertura que o Salesforce exige para implantações e pacotes. Quanto mais casos de teste seus testes cobrirem, maior a probabilidade de o seu código ser robusto. Às vezes, mesmo depois de escrever métodos de teste para todos os seus métodos de classe, a cobertura de código não chega a 100%. Uma causa comum é não cobrir todos os valores de dados referentes à execução de código condicional. Por exemplo, alguns valores de dados tendem a ser ignorados quando seu método de classe possui instruções if que fazem com que diferentes ramificações sejam executadas desde que a condição avaliada seja atendida. Garanta que seus métodos de teste tenham em consideração esses valores diferentes.

Esse exemplo inclui o método de classe getTaskPriority(), que contém duas instruções if. A principal tarefa deste método é retornar um valor de string prioritário com base no estado de lead informado. O método valida primeiramente o estado e retorna null se o estado for inválido. Se o estado for CA, o método retorna 'High' (Alto); caso contrário, retorna 'Normal' para qualquer outro valor de estado.

public with sharing class TaskUtil {
  public static String getTaskPriority(String leadState) {
    // Validate input
    if(String.isBlank(leadState) || leadState.length() > 2) {
      return null;
    }
    String taskPriority;
    if(leadState == 'CA') {
      taskPriority = 'High';
    } else {
      taskPriority = 'Normal';
    }
    return taskPriority;
  }
}
Note

O operador de igualdade (==) realiza comparações de strings sem diferenciar caracteres maiúsculos e minúsculos, por isso não há necessidade de primeiramente converter a string para caracteres minúsculos. Isso significa que receber 'ca' ou 'Ca' atenderá à condição de igualdade com a cadeia de caracteres literal 'CA'.

Esta é a classe de teste para o método getTaskPriority(). O método de teste simplesmente chama getTaskPriority() com um estado (NY).

@IsTest
private with sharing class TaskUtilTest {
  @IsTest
  static void testTaskPriority() {
    String pri = TaskUtil.getTaskPriority('NY');
    Assert.areEqual('Normal', pri);
  }
}

Vamos executar esta classe de teste (TaskUtilTest) no Web Console e verificar a cobertura de código para a classe TaskUtil correspondente que este teste cobre. Após o término da execução do teste, a cobertura de código para TaskUtil é mostrada como 75%.

Agora abra o arquivo TaskUtil.cls. Com esse arquivo aberto, clique em ícone de três barras na parte inferior da janela do Web Console para habilitar a configuração Highlight Apex Code Coverage (Destacar cobertura de código do Apex). Com essa configuração habilitada, você verá seis linhas verdes (cobertas) e duas linhas vermelhas (não cobertas) na classe TaskUtil, conforme mostrado nesta imagem.

Linhas cobertas para a classe TaskUtil no Web Console A configuração Highlight Apex Code Coverage (Destacar cobertura de código do Apex) está habilitada.

A linha 5 não está coberta porque nossa classe de teste não contém um teste para aprovar um parâmetro de estado inválido. Da mesma forma, a linha 11 não está coberta porque o método de teste não recebeu 'CA' como estado. Vamos adicionar mais dois métodos de teste para cobrir esses cenários. A seguir, apresentamos a classe de teste completa após adicionarmos os métodos de teste testTaskHighPriority() e testTaskPriorityInvalid(). Se executar novamente essa classe de teste, a cobertura de código para TaskUtil agora está em 100%!

@IsTest
private with sharing class TaskUtilTest {
  @IsTest
  static void testTaskPriority() {
    String pri = TaskUtil.getTaskPriority('NY');
    Assert.areEqual('Normal', pri);
  }
  @IsTest
  static void testTaskHighPriority() {
    String pri = TaskUtil.getTaskPriority('CA');
    Assert.areEqual('High', pri);
  }
  @IsTest
  static void testTaskPriorityInvalid() {
    String pri = TaskUtil.getTaskPriority('Montana');
    Assert.isNull(pri);
  }
}

Criar e executar um conjunto de testes

Um conjunto de testes é um conjunto de classes de teste do Apex que você executa juntas. Por exemplo, crie um conjunto de testes para ser executado sempre que você preparar uma implantação ou que a Salesforce liberar uma nova versão. Configure um conjunto de testes no Developer Console para definir um conjunto de classes de teste que são executadas juntas regularmente.

Agora você tem duas classes de teste em sua organização. Essas duas classes não estão relacionadas, mas por ora vamos fingir que estão. Suponhamos que haja situações em que você deseja executar essas duas classes de teste, mas não deseja executar todos os testes em sua organização. Crie um conjunto de testes que contenha ambas as classes e, em seguida, execute os testes no conjunto.

  1. Em Web Console (Console da Web), pressione Ctrl+Shift+P (Windows) ou ⌘+Shift+P (macOS) para abrir a paleta de comandos.
  2. Insira SFDX: Create Apex Test Suite e pressione Enter.
  3. Insira TempConverterTaskUtilSuite como nome do conjunto e pressione Enter.
  4. Selecione TaskUtilTest e TemperatureConverterTest e pressione Enter.
  5. Clique em Ícone de Testing (Testes) na barra de atividades. O painel lateral Testing (Testes) é aberto.
  6. Na barra de pesquisa Testing (Testes), insira TempConverterTaskUtilSuite.
  7. Para executar todos os testes no conjunto de testes, passe o cursor sobre a linha TempConverterTaskUtilSuite e clique em Ícone de Run Test Suite (Executar conjunto de testes).

Criar dados de teste

Os registros do Salesforce criados em métodos de teste não estão comprometidos com o banco de dados. Eles são revertidos quando a execução do teste é concluída. Esse comportamento de reversão é útil para testes porque você não tem que limpar seus dados de teste após o teste ser executado.

Por padrão, os testes do Apex não têm acesso aos dados preexistentes na organização, exceto para acesso a objetos de configuração e metadados, tais como os objetos Usuário ou Perfil. Configure os dados de teste dos seus testes. A criação de dados de teste deixa seus testes mais robustos e evita falhas causadas pela falta de dados ou por dados alterados na organização. Você pode criar dados de teste diretamente em seu método de teste ou utilizando uma classe de utilitário de teste, como veremos mais tarde.

Note

Mesmo esta não sendo uma prática recomendada, há momentos em que um método de teste precisa de acesso a dados preexistentes. Para acessar os dados da organização, anote o método de teste com @IsTest(SeeAllData=true). Os exemplos de métodos de teste desta unidade não acessam dados da organização e, portanto, não utilizam o parâmetro SeeAllData.

Quero saber mais

  • Você pode usar a Extensão Apex do Salesforce para o Visual Studio Code para executar testes do Apex e verificar a funcionalidade do seu código.
  • Você pode salvar até 6 MB de código do Apex em cada organização. As classes de teste anotadas com @IsTest não contam para esse limite.
  • Embora os dados de teste sejam revertidos, nenhum banco de dados à parte é utilizado para testes. Como resultado, para alguns sObjects que têm campos com restrições exclusivas, a inserção de registros duplicados sObject resulta em um erro.
  • Os métodos de teste não enviam emails.
  • Os métodos de teste não podem fazer callouts para serviços externos. Você pode usar callouts simulados nos testes.
  • As pesquisas SOSL realizadas em um teste retornam resultados vazios. Para garantir resultados previsíveis, utilize Test.setFixedSearchResults() para definir os registros a serem retornados pela pesquisa.

Recursos

Preparar-se para o desafio prático

Para completar o desafio prático desta unidade, você precisará criar uma nova classe do Apex chamada VerifyDate com o código copiado abaixo:

public with sharing class VerifyDate {
  //method to handle potential checks against two dates
  public static Date CheckDates(Date date1, Date date2) {
    //if date2 is within the next 30 days of date1, use date2.  Otherwise use the end of the month
    if(DateWithin30Days(date1,date2)) {
      return date2;
    } else {
      return SetEndOfMonthDate(date1);
    }
  }
  //method to check if date2 is within the next 30 days of date1
  private static Boolean DateWithin30Days(Date date1, Date date2) {
    //check for date2 being in the past
    if( date2 < date1) { return false; }
    //check that date2 is within (>=) 30 days of date1
    Date date30Days = date1.addDays(30); //create a date 30 days away from date1
    if( date2 >= date30Days ) { return false; }
    else { return true; }
  }
  //method to return the end of the month of a given date
  private static Date SetEndOfMonthDate(Date date1) {
    Integer totalDays = Date.daysInMonth(date1.year(), date1.month());
    Date lastDay = Date.newInstance(date1.year(), date1.month(), totalDays);
    return lastDay;
  }
}
Compartilhe seu feedback do Trailhead usando a Ajuda do Salesforce.

Queremos saber sobre sua experiência com o Trailhead. Agora você pode acessar o novo formulário de feedback, a qualquer momento, no site Ajuda do Salesforce.

Saiba mais Continue compartilhando feedback