GTest für HAL-Tests parametrisiert

Für eine HAL-Schnittstelle kann es mehrere Implementierungen geben. Um jede Instanz für eine HAL-Implementierung zu testen, wird standardmäßig ein wertparametrierter GTest geschrieben.

Grundlegende Testeinrichtung

Der GTest muss die Basisklasse testing::TestWithParam erben, deren Parameter der Name jeder Instanz ist. In der Methode SetUp kann der Dienst anhand des Instanznamens instanziiert werden, wie im folgenden Code-Snippet gezeigt.

// 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);
...
 }

Verwenden Sie für jede Testmethode das Makro TEST_P, wie im folgenden Beispiel gezeigt:

TEST_P(UsbHidlTest, setCallback) {
...
}

Instanzieren Sie die Suite mit dem Makro INSTANTIATE_TEST_SUITE_P, wie im folgenden Beispiel gezeigt:

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

Die Argumente sind:

  1. InstantiationName, was alles sein kann, was Ihrem Test entspricht. PerInstance ist ein gängiger Name.

  2. Der Name der Testklasse.

  3. Eine Sammlung von Instanznamen, die über die integrierte Methode abgerufen werden können, z. B. getAllHalInstanceNames.

  4. Die Methode zum Drucken des Namens der Testmethode. PrintInstanceNameToString ist ein vordefinierter Name, mit dem Sie einen Testnamen basierend auf dem Instanznamen und dem Namen der Testmethode erstellen können.

Mit mehreren Eingaben testen

GTest unterstützt Tupel für wertbezogene Tests. Wenn für einen HAL-Test mehrere Eingaben erforderlich sind (z. B. ein Test mit mehreren Schnittstellen), können Sie einen GTest mit tuple als Testparameter schreiben. Den vollständigen Code finden Sie unter VtsHalGraphicsMapperV2_1TargetTest.

Im Vergleich zu GTest mit einem einzelnen Testparameter muss für diesen Test tuple als Testparameter verwendet werden, wie im folgenden Beispiel gezeigt:

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())));

}

Wenn komplexere Parameter erforderlich sind, empfiehlt es sich, eine Struktur und benutzerdefinierte GTest-ToString-Funktionen zu verwenden.

Zum Instanziieren der Testsuite wird auch das Makro INSTANTIATE\_TEST\_CASE\_P verwendet, jedoch mit zwei Unterschieden:

  • Das dritte Argument ist eine Sammlung von Tupeln (im Vergleich zu einer Sammlung von Strings im Basisfall).
  • Die Methode zum Erstellen eines Testnamens muss tuple unterstützen. Sie können die integrierte Methode PrintInstanceTupleNameToString verwenden, mit der Tupel von Strings verarbeitet werden können, wie im folgenden Beispiel gezeigt:
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<>);