测试风格和命名

为了使查找、编写和使用KUnit测试尽可能简单,强烈建议按照以下准则命名和编写它们。虽然可以编写不遵循这些规则的KUnit测试,但它们可能会破坏某些工具,可能会与其他测试冲突,并且可能不会被测试系统自动运行。

建议仅在以下情况下偏离这些准则

  1. 将已知名称的测试移植到KUnit。

  2. 编写如果自动运行会导致严重问题的测试。 例如,非确定性地产生误报或误报,或者花费很长时间才能运行。

子系统、套件和测试

为了使测试易于查找,它们被分组到套件和子系统中。 测试套件是测试内核相关区域的一组测试。 子系统是一组测试套件,用于测试内核子系统或驱动程序的各个部分。

子系统

每个测试套件必须属于一个子系统。 子系统是一个或多个KUnit测试套件的集合,用于测试同一驱动程序或内核的一部分。 测试子系统应匹配单个内核模块。 如果被测试的代码无法编译为模块,在许多情况下,子系统应对应于源树中的目录或MAINTAINERS文件中的条目。 如果不确定,请遵循类似区域中的测试设置的约定。

测试子系统应以被测试的代码命名,要么以模块命名(如果可能),要么以被测试的目录或文件命名。 应命名测试子系统以避免必要的歧义。

如果测试子系统名称有多个组件,则应以下划线分隔。 请勿直接在子系统名称中包含“test”或“kunit”,除非我们实际上正在测试其他测试或kunit框架本身。 例如,子系统可以称为

ext4

匹配模块和文件系统名称。

apparmor

匹配模块名称和LSM名称。

kasan

该工具的通用名称,路径mm/kasan的突出部分

snd_hda_codec_hdmi

有几个组件(sndhdacodechdmi),用下划线分隔。 匹配模块名称。

避免使用如下例所示的名称

linear-ranges

名称应使用下划线,而不是短划线,来分隔单词。 优先使用linear_ranges

qos-kunit-test

该名称应使用下划线,并且不应以“kunit-test”作为后缀。 qos作为子系统名称也很模糊,因为内核的几个部分都有一个qos子系统。 power_qos会是一个更好的名字。

pc_parallel_port

对应的模块名称是parport_pc,所以这个子系统也应该命名为parport_pc

注意

KUnit API和工具没有明确地了解子系统。 它们是一种对测试套件进行分类和命名模块的方式,为人类提供了一种简单、一致的方式来查找和运行测试。 将来可能会发生变化。

套件

KUnit测试被分组到测试套件中,这些套件涵盖了被测的特定功能领域。 测试套件可以具有共享的初始化和关闭代码,这些代码针对套件中的所有测试运行。 并非所有子系统都需要拆分为多个测试套件(例如,简单的驱动程序)。

测试套件以它们所属的子系统命名。 如果子系统包含多个套件,则应将被测的特定区域附加到子系统名称,以下划线分隔。

如果在子系统中存在多种类型的测试使用KUnit(例如,单元测试和集成测试),则应将它们放入单独的套件中,并将测试类型作为套件名称中的最后一个元素。 除非这些测试实际存在,否则请避免在套件名称中使用_test_unittest或类似内容。

完整的测试套件名称(包括子系统名称)应指定为kunit_suite结构的.name成员,并构成模块名称的基础。 例如,测试套件可以包括

ext4_inode

ext4子系统的一部分,用于测试inode区域。

kunit_try_catch

kunit实现本身的一部分,用于测试try_catch区域。

apparmor_property_entry

apparmor子系统的一部分,用于测试property_entry区域。

kasan

kasan子系统只有一个套件,因此套件名称与子系统名称相同。

避免使用名称,例如

ext4_ext4_inode

没有理由两次声明子系统。

property_entry

没有子系统名称,套件名称不明确。

kasan_integration_test

因为在kasan子系统中只有一个套件,所以该套件应仅称为kasan。 不要冗余地添加integration_test。 它应该是一个单独的测试套件。 例如,如果添加了单元测试,则该套件可以命名为kasan_unittest或类似名称。

测试用例

单个测试包括一个测试受约束的代码路径,属性或功能的单个函数。 在测试输出中,单个测试的结果将显示为套件结果的子测试。

测试应以它们正在测试的内容命名。 这通常是被测函数的名称,并描述被测的输入或代码路径。 由于测试是C函数,因此应按照内核编码风格命名和编写它们。

注意

由于测试本身就是函数,因此它们的名称不能与内核中的其他C标识符冲突。 这可能需要一些创造性的命名。 最好使您的测试函数为static,以避免污染全局命名空间。

示例测试名称包括

unpack_u32_with_null_name

当传入NULL名称时,测试unpack_u32函数。

test_list_splice

测试list_splice宏。 它具有前缀test_,以避免与宏本身发生名称冲突。

如果需要在其测试套件的上下文之外引用测试,则测试的完全限定名称应为套件名称,后跟测试名称,以冒号分隔(即suite:test)。

测试Kconfig条目

每个测试套件都应绑定到一个Kconfig条目。

此Kconfig条目必须

  • 命名为CONFIG_<name>_KUNIT_TEST:其中<name>是测试套件的名称。

  • 与被测驱动程序/子系统的配置条目一起列出,或在[内核Hacking]->[内核测试和覆盖率]下

  • 依赖于CONFIG_KUNIT

  • 仅当未启用CONFIG_KUNIT_ALL_TESTS时才可见。

  • 具有CONFIG_KUNIT_ALL_TESTS的默认值。

  • 在帮助文本中简要描述KUnit。

如果我们无法满足上述条件(例如,测试无法构建为模块),则测试的Kconfig条目应为三态。

例如,Kconfig条目可能如下所示

config FOO_KUNIT_TEST
        tristate "KUnit test for foo" if !KUNIT_ALL_TESTS
        depends on KUNIT
        default KUNIT_ALL_TESTS
        help
          This builds unit tests for foo.

          For more information on KUnit and unit tests in general,
          please refer to the KUnit documentation in Documentation/dev-tools/kunit/.

          If unsure, say N.

测试文件和模块名称

KUnit测试通常编译为单独的模块。 为了避免与常规模块冲突,KUnit模块应以测试套件命名,后跟_kunit(例如,如果“foobar”是核心模块,则“foobar_kunit”是KUnit测试模块)。

测试源文件(无论是编译为单独的模块还是另一个源文件中的#include),最好保存在tests/子目录中,以免与其他源文件冲突(例如,用于制表符补全)。

请注意,在某些现有测试中也使用了_test后缀。 优先使用_kunit后缀,因为它使KUnit测试和非KUnit测试之间的区别更加清晰。

因此,对于常见情况,请将包含测试套件的文件命名为tests/<suite>_kunit.ctests目录应与被测代码位于同一级别。 例如,lib/string.c的测试位于lib/tests/string_kunit.c中。

如果套件名称包含测试的父目录的某些或全部名称,则修改源文件名以减少冗余可能是有意义的。 例如,foo_firmware套件可能位于foo/tests/firmware_kunit.c文件中。