GTest parametrizado para testes de HAL

Para uma interface HAL, pode haver várias implementações. Para testar cada instância de uma implementação do HAL, o método padrão é escrever um GTest com parâmetro de valor.

Configuração básica do teste

O GTest precisa herdar a classe base testing::TestWithParam, cuja variável é o nome de cada instância. No método SetUp, o serviço pode ser instanciado com base no nome da instância, conforme mostrado no snippet de código abaixo.

// The main test class for the USB hidl HAL
class UsbHidlTest : public testing::TestWithParam<std::string> {

 virtual void SetUp() override {
   usb = IUsb::getService(GetParam());
   ASSERT_NE(usb, nullptr);
...
 }

Para cada método de teste, use a macro TEST_P, conforme mostrado no exemplo abaixo:

TEST_P(UsbHidlTest, setCallback) {
...
}

Instânciar o pacote com a macro INSTANTIATE_TEST_SUITE_P, conforme mostrado no exemplo a seguir:

INSTANTIATE_TEST_SUITE_P(
       PerInstance, UsbHidlTest,
       testing::ValuesIn(android::hardware::getAllHalInstanceNames(IUsb::descriptor)),
       android::hardware::PrintInstanceNameToString);

Os argumentos são:

  1. InstantiationName, que pode ser qualquer coisa que corresponde ao seu teste. PerInstance é um nome comum.

  2. O nome da classe de teste.

  3. Uma coleção de nomes de instâncias, que pode ser recuperada do método integrado, por exemplo, getAllHalInstanceNames.

  4. O método para mostrar o nome do método de teste. PrintInstanceNameToString é um nome integrado que pode ser usado para compilação de um nome de teste com base no nome da instância e do método de teste.

Testar com várias entradas

O GTest oferece suporte a tuplas para testes parametrizados por valor. Quando um teste HAL exige testes com várias entradas (por exemplo, um teste com várias interfaces), é possível gravar um GTest com tuple como o parâmetro de teste. O código completo pode ser encontrado em VtsHalGraphicsMapperV2_1TargetTest.

Em comparação com o GTest com um único parâmetro de teste, esse teste precisa usar tuple como o parâmetro de teste, conforme mostrado no exemplo abaixo:

class GraphicsMapperHidlTest
   : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
 protected:
   void SetUp() override {
       ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>(std::get<0>(GetParam()),
                                                                    std::get<1>(GetParam())));

}

Se forem necessários parâmetros mais complicados, é recomendável usar uma estrutura e funções ToString personalizadas do GTest.

Para instanciar o pacote de testes, a macro INSTANTIATE\_TEST\_CASE\_P também é usada, com duas diferenças:

  • O terceiro argumento é uma coleção de tuplas (em vez de uma coleção de strings, no caso básico).
  • O método para compilar um nome de teste precisa oferecer suporte a tuple. Você pode usar o método integrado PrintInstanceTupleNameToString, que pode processar tuplas de strings, conforme mostrado no exemplo a seguir:
INSTANTIATE_TEST_CASE_P(
       PerInstance, GraphicsMapperHidlTest,
       testing::Combine(
               testing::ValuesIn(
                       android::hardware::getAllHalInstanceNames(IAllocator::descriptor)),
           testing::ValuesIn(android::hardware::getAllHalInstanceNames(IMapper::descriptor))),
       android::hardware::PrintInstanceTupleNameToString<>);