1 Yocto 项目测试环境手册
目录
1.1欢迎
欢迎阅读 Yocto 项目测试环境手册!本手册正在编写中。该手册包含有关 Yocto 项目使用的测试环境的信息,以确保每个主要和次要版本都能按预期工作。项目的所有测试基础设施和流程都是公开可见和可用的,因此社区可以看到正在执行的测试、如何完成以及测试和项目在任何给定时间的当前状态。其他组织可以利用 Yocto 项目使用的流程和测试环境,在项目核心的基础上创建自己的自动化生产测试环境。
目前,Yocto 项目测试环境手册没有预计的发布日期。本手册正在编写中,最初加载了 README 文件中的信息和关键工程师的注释:
-
yocto-autobuilder2:这个 README.md 是主要的 README,它详细说明了如何设置 Yocto Project Autobuilder。该
yocto-autobuilder2
信息库代表Yocto计划的控制台UI插件Buildbot和必要的配置Buildbot的配置来执行项目需要测试。 -
yocto-autobuilder-helper:此README 和存储库包含 Yocto Project Autobuilder Helper 脚本和配置。该
yocto-autobuilder-helper
库包含的“胶水”的逻辑,用来定义测试运行以及如何运行它们。因此,任何持续改进 (CI) 系统都可以使用它来运行构建、支持获取正确的代码修订、配置构建和层、运行构建和收集结果。代码独立于任何 CI 系统,这意味着代码可以在Buildbot、Jenkins 或其他系统上运行。此存储库的每个项目版本都有一个分支,定义要在每个版本的基础上运行的测试。
1.2 Yocto 项目自动构建器概述
Yocto 项目自动构建器统称为 Yocto 项目使用的软件、工具、脚本和程序,以自动化和常规方式跨支持的硬件测试已发布的软件。基本上,在 Yocto 项目版本的开发过程中,Autobuilder 会测试一切是否正常。Autobuilder 构建所有测试目标并运行所有测试。
Yocto 项目现在使用标准的上游 Buildbot(版本 9)来驱动其集成和测试。Buildbot Nine 有一个插件界面,Yocto 项目使用yocto-autobuilder2
存储库中的代码对其进行自定义 ,并添加了自己的控制台 UI 插件。生成的 UI 插件允许您以适合项目需求的方式可视化构建。
一个helper
层提供通过找到脚本配置和作业管理yocto-autobuilder-helper
信息库。该 helper
层包含大部分构建配置信息并且是特定于版本的,这使得它可以在每个项目的基础上高度可定制。该层与 CI 系统无关,包含许多帮助程序脚本,可以从简单的 JSON 文件生成构建配置。
注意
该项目使用 Buildbot 是出于历史原因,也是因为许多项目开发人员都具备 Python 知识。可以使用另一个持续集成 (CI) 系统(例如 Jenkins) 的外层而不是 Buildbot。
下图显示了 Yocto Project Autobuilder 堆栈,其拓扑包括一个控制器和一个工作器集群:
1.3 Yocto 项目测试 - 测试类型概述
Autobuilder 通过使用以下类型的测试来测试项目的不同元素:
-
构建测试:测试是否通过不同的MACHINE、 DISTRO、其他配置选项以及正在构建的特定目标图像(或世界)来构建特定配置。用于在 Autobuilder 上触发所有不同测试配置的构建。构建通常涵盖不同架构、机器和发行版的许多不同目标,以及不同的配置,例如不同的初始化系统。Autobuilder 可以测试数百种配置和目标。
-
构建过程中的健全性检查:通过疯狂 类启动的测试。这些检查确保构建的输出是正确的。例如,生成的二进制文件中的 ELF 架构是否与目标系统匹配?ARM 二进制文件在 MIPS 系统中不起作用!
-
-
构建性能测试:测试构建过程中常用的步骤是否有效工作并避免回归。对时间常用的使用场景进行了测试
oe-build-perf-test
。这些测试在隔离的机器上运行,因此测试的时间测量是准确的,并且没有其他过程干扰计时结果。该项目目前在两个不同的发行版(Fedora 和 Ubuntu)上测试性能,以确保我们没有单点故障并确保不同的发行版有效工作。 -
eSDK 测试:通过以下命令启动图像测试:
$ bitbake image -c testsdkext
测试使用
testsdkext
类和do_testsdkext
任务。 -
功能测试:通过OpenEmbedded Self test (oe-selftest)运行各种基于场景的测试 。我们在我们支持的每个主要发行版上测试 oe-selftest。
-
图像测试:通过以下命令启动图像测试:
$ bitbake image -c testimage
测试使用testimage* 类和do_testimage任务。
-
层测试: Autobuilder 可以测试特定层是否适用于系统测试。测试的层可以由项目成员选择。一些关键的社区层也会定期进行测试。
-
包测试:包测试 (ptest) 对目标机器上的 OpenEmbedded 构建系统构建的包运行测试。有关Ptest的更多信息,请参阅Yocto 项目开发任务手册中的 测试包与 ptest部分和“ Ptest ” Wiki 页面。
-
SDK 测试:通过以下命令启动图像测试:
$ bitbake image -c testsdk
测试使用了testsdk类和
do_testsdk
任务。 -
单元测试:对系统各个组件的单元测试通过bitbake-selftest和 oe-selftest 运行。
-
自动升级助手:此目标测试是否有新版本的软件可用以及我们是否可以自动升级到这些新版本。如果是这样,该目标会通过电子邮件向维护人员发送补丁,让他们知道这是可能的。
1.4测试如何映射到代码区域
测试映射到代码库中,如下所示:
-
bitbake-selftest:
这些测试是独立的,测试 BitBake 及其 API,其中包括 fetcher。测试位于
bitbake/lib/*/tests
.从 BitBake 存储库中,运行以下命令:
$ bitbake-selftest
要跳过访问 Internet 的测试,请
BB_SKIP_NETTEST
在运行“bitbake-selftest”时使用该变量,如下所示:$ BB_SKIP_NETTEST=yes bitbake-selftest
默认输出是安静的,只打印运行内容的摘要。要查看更多信息,有一个详细选项:
$ bitbake-selftest -v
当您希望跳过访问网络的测试时使用此选项,这些测试通常是测试 fetcher 模块所必需的。要指定要运行的单个测试模块,请将测试模块名称附加到“bitbake-selftest”命令。例如,要为 bb.data.module 指定测试,请运行:
$ bitbake-selftest bb.test.data.module
您还可以通过定义全名和模块以及测试的类路径来指定单个测试,例如:
$ bitbake-selftest bb.tests.data.TestOverrides.test_one_override
这些测试基于Python unittest。
-
oe-自测:
-
这些测试使用 OE 来测试工作流,包括测试特定功能、任务行为和 API 单元测试。
-
测试可以通过“-j”选项利用并行性,该选项可以指定多个线程来分布测试。请注意,来自给定测试类的所有测试都将在同一线程中运行。要并行化大量测试,您可以将类拆分为多个单元。
-
这些测试基于 Python unittest。
-
测试代码位于
meta/lib/oeqa/selftest/cases/
. -
要运行所有测试,请输入以下命令:
$ oe-selftest -a
-
要运行特定测试,请使用以下命令形式,其中 testname 是特定测试的名称:
$ oe-selftest -r <testname>
例如,以下命令将运行 tinfoil getVar API 测试:
$ oe-selftest -r tinfoil.TinfoilTests.test_getvar
也可以运行一组测试。例如,以下命令将运行所有锡纸测试:
$ oe-selftest -r tinfoil
-
-
测试图像:
-
这些测试构建一个映像,启动它,并针对该映像的内容运行测试。
-
这些测试的代码位于
meta/lib/oeqa/runtime/cases/
. -
您需要按如下方式设置IMAGE_CLASSES变量:
IMAGE_CLASSES += "testimage"
-
使用以下命令形式运行测试:
$ bitbake image -c testimage
-
-
测试版:
-
这些测试构建一个 SDK,安装它,然后针对该 SDK 运行测试。
-
这些测试的代码位于
meta/lib/oeqa/sdk/cases/
. -
使用以下命令形式运行测试:
$ bitbake image -c testsdk
-
-
测试dk_ext:
-
这些测试构建一个扩展 SDK (eSDK),安装该 eSDK,然后针对 eSDK 运行测试。
-
这些测试的代码位于
meta/lib/oeqa/esdk
. -
要运行测试,请使用以下命令形式:
$ bitbake image -c testsdkext
-
-
oe-build-perf-test:
-
这些测试贯穿常用的使用场景并测量性能时间。
-
这些测试的代码位于
meta/lib/oeqa/buildperf
. -
要运行测试,请使用以下命令形式:
$ oe-build-perf-test <options>
该命令有许多选项,例如放置测试结果的位置。Autobuilder Helper Scripts 包括
build-perf-test-wrapper
带有如何从命令行使用 oe-build-perf-test 的示例的脚本。使用该
oe-git-archive
命令将测试结果存储到 Git 存储库中。使用该
oe-build-perf-report
命令生成带有性能数据图表的文本报告和 HTML 报告。例如,请参阅 https://downloads.yoctoproject.org/releases/yocto/yocto-2.7/testresults/buildperf-centos7/perf-centos7.yoctoproject.org_warrior_20190414204758_0e39202.html 和 https://downloads/releases/project.org yocto/yocto-2.7/testresults/buildperf-centos7/perf-centos7.yoctoproject.org_warrior_20190414204758_0e39202.txt。 -
测试包含在
lib/oeqa/buildperf/test_basic.py
.
-
1.5测试示例
本节为“测试如何映射到代码区域”一节中列出的每个测试提供示例测试 。
对于 oeqa 测试,每个区域的测试用例位于目录的主测试目录中meta/lib/oeqa/selftest/cases
。
对于 oe-selftest。bitbake 测试用例驻留在lib/bb/tests/
目录中。
1.5.1 bitbake-selftest
一个简单的测试示例来自lib/bb/tests/data.py
:
class DataExpansions(unittest.TestCase):
def setUp(self):
self.d = bb.data.init()
self.d["foo"] = "value_of_foo"
self.d["bar"] = "value_of_bar"
self.d["value_of_foo"] = "value_of_'value_of_foo'"
def test_one_var(self):
val = self.d.expand("${foo}")
self.assertEqual(str(val), "value_of_foo")
在这个例子中,DataExpansions
创建了一个测试类,从标准的 python unittest 派生出来。该类有一个公共setUp
功能,该功能由该类中的所有测试共享。然后添加一个简单的测试来测试扩展变量时是否找到了正确的值。
Bitbake 自测是简单的 Python 单元测试。有关编写这些测试的更多信息,请参阅 Python unittest 文档:https : //docs.python.org/3/library/unittest.html。
1.5.2 oe-selftest
由于完整构建所需的幕后设置,这些测试更加复杂。代码没有直接使用 Python 的 unittest,而是包装了大部分标准对象。测试可以很简单,例如使用以下示例在 OE 构建环境中测试命令:
class BitbakeLayers(OESelftestTestCase):
def test_bitbakelayers_showcrossdepends(self):
result = runCmd('bitbake-layers show-cross-depends')
self.assertTrue('aspell' in result.output, msg = "No dependencies were shown. bitbake-layers show-cross-depends output: %s"% result.output)
此示例取自meta/lib/oeqa/selftest/cases/bblayers.py
,从OESelftestTestCase
派生自 的类创建了一个测试用例unittest.TestCase
,它运行bitbake-layers
命令并检查输出以确保它包含我们知道应该在这里的内容。
该oeqa.utils.commands
模块包含可以协助完成常见任务的助手,包括:
-
获取一个 bitbake 变量的值:使用
oeqa.utils.commands.get_bb_var()
或oeqa.utils.commands.get_bb_vars()
用于多个变量 -
为构建运行 bitbake 调用:使用
oeqa.utils.commands.bitbake()
-
运行命令:使用
oeqa.utils.commandsrunCmd()
还有一个oeqa.utils.commands.runqemu()
功能可以启动runqemu
命令以在运行的虚拟化映像中测试事物。
您可以并行运行这些测试。并行对每个测试类起作用,因此给定测试类中的测试应始终在同一构建中运行,而不同类或模块中的测试可能会被拆分为不同的构建。由于测试启动bitbake
命令并存在于其上下文之外,因此没有可用于这些测试的数据存储。因此,常见的 bitbake 库函数 (bb.*) 也无法使用。
1.5.3 testimage
这些测试在映像启动并运行后运行,无论是在目标硬件上还是在 QEMU 下。因此,假设它们在目标映像环境中运行,而不是在主机构建环境中运行。来自的一个简单示例meta/lib/oeqa/runtime/cases/python.py
包含以下内容:
class PythonTest(OERuntimeTestCase):
@OETestDepends(['ssh.SSHTest.test_ssh'])
@OEHasPackage(['python3-core'])
def test_python3(self):
cmd = "python3 -c \\"import codecs; print(codecs.encode('Uryyb, jbeyq', 'rot13'))\""
status, output = self.target.run(cmd)
msg = 'Exit status was not 0. Output: %s' % output
self.assertEqual(status, 0, msg=msg)
在此示例中,OERuntimeTestCase
该类将 unittest.TestCase
. 在测试中,self.target
代表目标系统,其中可以使用该run()
方法在其上运行命令。
为确保满足某些测试或包依赖项,您可以使用 OETestDepends
和OEHasPackage
装饰器。例如,只有在映像中安装了 python3-core 时,此示例中的测试才有意义。
1.5.4 testsdk_ext
这些测试针对构建的可扩展 SDK (eSDK) 运行。测试可以假设已经设置了 eSDK 环境。来自的示例 meta/lib/oeqa/sdk/cases/devtool.py
包含以下内容:
class DevtoolTest(OESDKExtTestCase):
@classmethod def setUpClass(cls):
myapp_src = os.path.join(cls.tc.esdk_files_dir, "myapp")
cls.myapp_dst = os.path.join(cls.tc.sdk_dir, "myapp")
shutil.copytree(myapp_src, cls.myapp_dst)
subprocess.check_output(['git', 'init', '.'], cwd=cls.myapp_dst)
subprocess.check_output(['git', 'add', '.'], cwd=cls.myapp_dst)
subprocess.check_output(['git', 'commit', '-m', "'test commit'"], cwd=cls.myapp_dst)
@classmethod
def tearDownClass(cls):
shutil.rmtree(cls.myapp_dst)
def _test_devtool_build(self, directory):
self._run('devtool add myapp %s' % directory)
try:
self._run('devtool build myapp')
finally:
self._run('devtool reset myapp')
def test_devtool_build_make(self):
self._test_devtool_build(self.myapp_dst)
本例中对devtool
命令进行测试,看是否可以在eSDK中使用该命令构建示例应用。devtool build
1.5.5 testsdk
这些测试针对构建的 SDK 运行。这些测试可以假设已经提取了一个 SDK 并且已经获取了它的环境文件。来自的一个简单示例meta/lib/oeqa/sdk/cases/python2.py
包含以下内容:
class Python3Test(OESDKTestCase):
def setUp(self):
if not (self.tc.hasHostPackage("nativesdk-python3-core") or
self.tc.hasHostPackage("python3-core-native")):
raise unittest.SkipTest("No python3 package in the SDK")
def test_python3(self):
cmd = "python3 -c \\"import codecs; print(codecs.encode('Uryyb, jbeyq', 'rot13'))\""
output = self._run(cmd)
self.assertEqual(output, "Hello, world\n")
在此示例中,如果 nativesdk-python3-core 已安装到 SDK 中,则代码会使用基本命令运行 python3 解释器以检查其是否正常工作。只有在 SDK 中安装了 python3 时,测试才会运行。
1.5.6 oe-build-perf-test
性能测试通常测量操作需要多长时间以及发生这种情况时的资源利用率。来自的示例 meta/lib/oeqa/buildperf/test_basic.py
包含以下内容:
class Test3(BuildPerfTestCase):
def test3(self):
"""Bitbake parsing (bitbake -p)"""
# Drop all caches and parse
self.rm_cache()
oe.path.remove(os.path.join(self.bb_vars['TMPDIR'], 'cache'), True)
self.measure_cmd_resources(['bitbake', '-p'], 'parse_1',
'bitbake -p (no caches)')
# Drop tmp/cache
oe.path.remove(os.path.join(self.bb_vars['TMPDIR'], 'cache'), True)
self.measure_cmd_resources(['bitbake', '-p'], 'parse_2',
'bitbake -p (no tmp/cache)')
# Parse with fully cached data
self.measure_cmd_resources(['bitbake', '-p'], 'parse_3',
'bitbake -p (cached)')
这个例子展示了如何测量三个特定的解析时间,有和没有各种缓存,以显示 BitBake 的解析性能随时间的变化趋势。
1.6编写测试时的注意事项
在编写好的测试时,需要记住几件事。由于在 Autobuilder 上运行的事物由多个工作人员同时访问,请考虑以下事项:
不允许运行“cleanall”。
这可以从 DL_DIR 中删除文件,这可能会破坏并行运行的其他构建。如果需要,必须将 DL_DIR 设置为隔离目录。
不允许运行“cleansstate”。
这可以从 SSTATE_DIR 中删除文件,这可能会破坏并行运行的其他构建。如果需要,则必须将 SSTATE_DIR 设置为隔离目录。或者,您可以在bitbake
命令中使用“-f”选项,通过更改 sstate 校验和来“污染”任务,以确保不会重用 sstate 缓存项。
测试不应更改元数据。
对于 oe-selftests 尤其如此,因为它们可以并行运行,并且更改元数据会导致更改校验和,这会在并行运行时混淆 BitBake。如果有必要,请将图层复制到临时位置并进行修改。一些测试需要更改元数据,例如 devtool 测试。为了保护元数据不受更改,请先设置该数据的临时副本。