2023年8月

ChromeOS 将分离浏览器和操作系统

现在的 ChromeOS 的系统用户界面和浏览器是同一个二进制程序,谷歌的一个已经进行了两年的项目将把它们分开,并很快将向大众推出。该项目名为 “Lacros”,这将把 ChromeOS 的 Linux 操作系统从 Chrome 浏览器中分离出来,让谷歌可以独立更新每个部分。此举的一个意图是加入更多对 Wayland 的支持。ChromeOS 此前使用的是谷歌自己开发的图形栈 Freon,而 Wayland 已经在包括安卓在内的 Linux 系统和应用中得到了广泛使用,它将作为 ChromeOS 的原生图形栈使用。分开后,谷歌也将无需为 ChromeOS 定制 Chrome,可以直接使用 Chrome 的 Linux 版本。

消息来源:Ars Technica
老王点评:那为什么当年要合在一起,用自己的一个图形栈?秀技术吗?

40% 基于 Arm 的服务器部署在中国

虽然绝大多数服务器仍在使用 AMD 和英特尔的 x86 芯片,但这些芯片都是美国公司生产的,由于美国的贸易限制,中国公司越来越难获得先进的芯片。相比之下,Arm 架构可以获得全球芯片制造商的许可。最新数据显示,全球近 10% 的服务器采用了 Arm 处理器,其中 40% 位于中国。此外,Canalys CEO 去年指出,99% 的智能手机、97% 的平板电脑和 9% 的个人电脑都使用了 Arm 芯片,并声称 16% 的公共云已经基于 Arm。他预测,到 2026 年,50% 出售给公共云的 CPU 将基于 ARM,而不是 x86。

消息来源:The Register
老王点评:Arm 真是异军突起,但是我还是更看好 RISC-V。

Meta 开源从文本中创建音乐的人工智能工具

Meta 公司周三开源了名为 AudioCraft 的人工智能工具,它将帮助用户根据文本提示创建音乐和音频。该人工智能工具可用于音乐、声音、压缩和生成。Meta 说,它使用了该公司拥有的和特别授权的音乐进行了训练。不像通过文本创建图像的人工智能工具,生成音乐的工具进展相对滞后。Meta 说,“有一些工作已经完成,但非常复杂,而且不是很开放,所以人们不能轻松使用。”AudioCraft 以 MIT 许可证发布,Meta 希望“为更广泛的社区做出贡献,为音频和音乐实验提供可访问的工具。”

消息来源:Ars Technica
老王点评:所以,以后音乐也不需要专业人员制作了么?

揭开 Linux 中退出码的神秘面纱。了解什么是退出码,以及为什么和如何使用它们。

退出码(退出状态)可以告诉我们最后一次执行的命令的状态。在命令结束以后,我们可以知道命令是成功完成的还是以错误结束的。

其基本思想是,程序返回退出代码 0 时表示执行成功,没有问题。代码 10 以外的任何代码都被视为不成功。

退出码除了 0 和 1 外还有很多值,我将在本文介绍它们。

Linux Shell 中的各种退出码

我们来快速了解一下 Linux Shell 中的主要退出码:

退出码解释
0命令成功执行
1通用错误代码
2命令(或参数)使用不当
126权限被拒绝(或)无法执行
127未找到命令,或 PATH 错误
128+n命令被信号从外部终止,或遇到致命错误
130通过 Ctrl+CSIGINT 终止(终止代码 2 或键盘中断
143通过 SIGTERM 终止(默认终止
255/*退出码超过了 0-255 的范围,因此重新计算(LCTT 译注:超过 255 后,用退出码对 256 取模)
? 130SIGINT^C)和 143SIGTERM)等终止信号是非常典型的,它们属于 128+n 信号,其中 n 代表终止码。

在简单了解了退出码之后,我们来看看它们的用法。

获取退出码

前一个命令执行的退出码存储在 特殊变量 $? 中。你可以通过运行以下命令来获取:

echo $?

我们在所有演示中都将使用它来获取退出代码。

请注意,exit 命令支持以带着前一条命令相同的退出码退出。

退出码 0

退出码 0 表示命令执行无误,这是完成命令的理想状态。

例如,我们运行这样一条基本命令

neofetch 

echo $?

这个退出码 0 表示特定命令已成功执行,仅此而已。让我们再演示几个例子。

你可以尝试 终止一个进程;它也会返回代码 0

pkill lxappearance

查看文件内容也会返回退出码 0,这意味着 cat 命令执行成功。

退出码 1

退出码 1 也很常见。它通常表示命令以一般错误结束。

例如,在没有 sudo 权限的情况下使用 软件包管理器,就会返回代码 1。在 Arch Linux 中,如果我运行下面的命令:

pacman -Sy

它会返回 1, 表示上一条命令运行出错。

exit code 1 (impermissible operation resulted in this code)

? 如果你在基于 Ubuntu 的发行版中尝试这样做(不使用 sudo 执行 apt update),运行后会得到错误码 100,表示你是在没有权限的情况下运行 apt100 不是标准错误码,而是 apt 特有的错误码。

虽然这是一般的理解,但我们也可以将其解释为 “不被允许的操作”。

除以 0 等操作也会返回错误码 1

Division by zero results in code 1

退出码 2

这个退出码出现在当执行的命令有语法错误时。滥用命令参数也会导致此错误。

一般来说,它表示由于使用不当,命令无法执行。

例如,我在一个本应只有一个连字符的选项上添加了两个连字符,那么此时会出现退出码 2。

grep --z file.txt

Invalid argument resulted in exit code 2

当权限被拒绝时,比如访问 /root 文件夹,就会出现错误码 2

Permission denied gives out code 2

退出码 126

126 是一个特殊的退出码,它用于表示命令或脚本因权限错误而未被执行。

当你尝试执行没有执行权限的 Shell 脚本时,就会出现这个错误。

请注意,该退出码只出现在没有足够权限的脚本或命令的“执行”中,这与一般的权限被拒绝错误不同。

因此,不要把它与你之前看到的退出码为 2 的示例混淆。在那个示例中,运行的是 ls 命令,权限问题出自它试图执行的目录。而本例中权限问题来自脚本本身。

退出码 127

这是另一个常见的退出码。退出码 127 指的是“未找到命令”。它通常发生在执行的命令有错别字或所需的可执行文件不在 $PATH 变量中时。

例如,当我尝试执行一个不带路径的脚本时,经常会看到这个错误。

Script executed without the path gives "command not found" or code 127

当你想运行的可执行文件不在 $PATH 变量中时,也会出现退出码 127。你可以通过 在 PATH 变量中添加命令的目录 来纠正这种情况。

当你输入不存在的命令时,也会得到这样的退出码。

Unmount is not a command, and Screenfetch is not installed, which resulted in code 127

退出码 128+n 系列

当应用程序或命令因致命错误而终止或执行失败时,将产生 128 系列退出码(128+n),其中 n 为信号编号。

n 包括所有类型的终止代码,如 SIGTERMSIGKILL 等。

退出码 130 或 SIGINT

在通过终止信号 2 或按下 Ctrl+C 中断进程时,会发出 SIGINT(键盘中断信号)。

因为终止信号是 2,所以我们得到的退出码是 130(128+2)。下面的视频演示了 lxappearance 的中断信号。

退出码 137 或 SIGKILL

SIGKILL(立即终止信号)表示终止信号 9。这是终止应用程序时最不应该使用的方法。

因为终止信号为 9,因此我们得到的退出代码为 137(128+9)。

退出码 143 或 SIGTERM

SIGTERM 是进程在未指定参数的情况下被杀死时的默认行为。

SIGTERM 的终止信号为 15,因此该信号的退出码为 143(128+15)。

还有一些你以前可能不知道的终止信号,它们也有自己类似的退出码。你可以在这里查看它们:

? 请注意,如果进程在启动它的同一会话中终止,这些信号可能不会出现。如果要重现这些信号,请从不同的 shell 终止。

就个人而言,信号 128 是无法重现的。

当退出码超过了 255 会怎样?

最新版本的 Bash 甚至保留了超过 255 的原始退出码的值,但一般来说,如果代码超过 255,就会被重新计算。

也就是说,代码 256 会变成 0257 会变成 1383 会变成 127,以此类推。为确保更好的兼容性,请将退出码保持在 0255 之间。

结语

希望你对 Linux Shell 中的退出码有所了解。在排查各种问题时,使用它们会非常方便。

如果你要在 Shell 脚本中使用这些代码,请确保你了解每个代码的含义,以便更容易地排除故障。

这就是本文的全部内容。如有遗漏,请在评论区告诉我。

(题图:MJ/719ff711-1b9f-4aa9-a82e-980704acbdd8)


via: https://itsfoss.com/linux-exit-codes/

作者:Pranav Krishna 选题:lkxed 译者:lxbwolf 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用 Linux 的一个好处是可以选择多种不同的桌面环境。Fedora Linux 官方的 Workstation 版本默认使用 GNOME 作为桌面环境,但是你可以通过 Fedora 定制版 Spin 选择另一个桌面环境作为默认环境。本文将更详细地介绍 Fedora Linux 定制版。你可以在我之前的文章《Fedora Linux 的各种版本》中找到所有 Fedora Linux 变体的概述。

KDE Plasma 桌面

这个 Fedora Linux 定制版使用 KDE Plasma 作为默认的桌面环境。KDE Plasma 是一个优雅的桌面环境,非常易于定制。因此,你可以根据自己的喜好自由地定制桌面的外观。你可以定制你喜欢的主题,安装所需的小部件,更换图标、字体,根据个人喜好定制面板,并从社区安装各种扩展功能。

Fedora Linux KDE Plasma 桌面预装了许多常用的应用程序。你可以使用 Firefox、Kontact、Telepathy、KTorrent 和 KGet 上网。LibreOffice、Okular、Dolphin 和 Ark 可满足你的办公需求。而针对多媒体需求,该版本提供了 Elisa、Dragon Player、K3B 和 GwenView 等多个应用程序。

Fedora KDE Plasma Desktop

更多信息请参考以下链接:

Fedora Linux KDE Plasma 桌面

XFCE 桌面

这个版本非常适合那些希望在外观定制和性能之间取得平衡的用户。XFCE 本身被设计为快速轻巧,但仍具有吸引人的外观。这个桌面环境逐渐受到老旧设备用户的欢迎。

Fedora Linux XFCE 安装了多种适合日常需求的应用程序,包括 Firefox、Pidgin、Gnumeric、AbiWord、Ristretto、Parole 等。Fedora Linux XFCE 还提供了一个系统设置菜单,让你更轻松地配置 Fedora Linux。

Fedora XFCE Desktop

更多信息请访问此链接:

Fedora Linux XFCE 桌面

LXQT 桌面

这个版本带有一个轻量级的 Qt 桌面环境,专注于现代经典的桌面体验,而不会降低系统性能。这个 Fedora Linux 版本包含基于 Qt5 工具包的应用程序,并采用 Breeze 主题。你可以通过内置的应用程序如 QupZilla、QTerminal、FeatherPad、qpdfview、Dragon Player 等来进行各种日常活动。

Fedora LXQt Desktop

更多信息请访问此链接:

Fedora Linux LXQT 桌面

MATE-Compiz 桌面

Fedora Linux MATE Compiz 桌面是 MATE 和 Compiz Fusion 的组合。MATE 桌面环境使这个 Fedora Linux 版本能够通过优先考虑生产力和性能来发挥最佳效果。同时,Compiz Fusion 使用 Emerald 和 GTK+ 主题为系统提供了美观的 3D 外观。这个 Fedora Linux 版本还配备了各种流行的应用程序,如 Firefox、LibreOffice、Parole、FileZilla 等。

Fedora Mate-Compiz Desktop

更多信息请访问此链接:

Fedora Linux MATE Compiz 桌面

Cinnamon 桌面

由于其用户友好的界面,Fedora Linux Cinnamon 桌面非常适合那些可能对 Linux 操作系统不太熟悉的用户。你可以轻松理解如何使用这个 Fedora Linux 版本。这个定制版内置了各种准备好供你日常使用的应用程序,如 Firefox、Pidgin、GNOME Terminal、LibreOffice、Thunderbird、Shotwell 等。你可以使用 Cinnamon 设置应用来配置你的操作系统。

Fedora Cinnamon Desktop

更多信息请访问此链接:

Fedora Linux Cinnamon 桌面

LXDE 桌面

Fedora Linux LXDE 桌面拥有一个快速运行的桌面环境,但设计旨在保持低资源使用。这个定制版专为低配置硬件设计,如上网本、移动设备和旧电脑。Fedora Linux LXDE 配备了轻量级和流行的应用程序,如 Midori、AbiWord、Osmo、Sylpheed 等。

Fedora LXDE Desktop

更多信息请访问此链接:

Fedora Linux LXDE 桌面

SoaS 桌面

SoaS 是 “Sugar on a Stick” 的缩写。Fedora Linux Sugar 桌面是一个面向儿童的学习平台,因此它具有非常简单的界面,易于儿童理解。这里的 “stick” 是指一个随身驱动器或存储“棒”。这意味着这个操作系统体积紧凑,可以完全安装在一个随身 U 盘上。学童可以将他们的操作系统携带在随身 U 盘上,这样他们可以在家、学校、图书馆和其他地方轻松使用。Fedora Linux SoaS 拥有各种有趣的儿童学习应用程序,如 Browse、Get Books、Read、Turtle Blocks、Pippy、Paint、Write、Labyrinth、Physic 和 FotoToon。

Fedora SOAS Desktop

更多信息请访问此链接:

Fedora Linux Sugar 桌面

i3 Tiling WM

Fedora Linux 的 i3 Tiling WM 定制版与其他不太相同。这个 Fedora Linux 定制版不使用桌面环境,而只使用窗口管理器。所使用的窗口管理器是 i3,它是 Linux 用户中非常受欢迎的平铺式窗口管理器。Fedora i3 定制版适用于那些更注重使用键盘进行交互而非鼠标或触摸板的用户。这个 Fedora Linux 定制版配备了各种应用程序,如 Firefox、NM Applet、brightlight、azote、htop、mousepad 和 Thunar。

Fedora i3 Tiling WM

更多信息请访问此链接:

Fedora Linux i3 Tiling WM

结论

Fedora Linux 通过 Fedora Linux 定制版提供了大量的桌面环境选择。你只需选择一个 Fedora 定制版,即可享受你选择的桌面环境以及其内置的即用应用程序。你可以在 https://spins.fedoraproject.org/ 找到关于 Fedora 定制版的完整信息。

(题图:MJ/6e7ea0c7-ccbe-4664-af60-61345a7c6617)


via: https://fedoramagazine.org/fedora-linux-editions-part-2-spins/

作者:Arman Arisman 选题:lkxed 译者:ChatGPT 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

仅 100KB 大小,只需 4 分钟训练的人工智能图像生成器

英伟达最新发表的论文披露了一种名为 Perfusion 的全新文本到图像的个性化创新方法。它并不像竞争对手那样是一款价值百万美元的超重量级模型。Perfusion 的大小仅为 100KB,训练时间为 4 分钟,在保持个性化概念身份的同时,还能在描绘个性化概念方面实现极大的创造灵活性。尽管它的体积很小,在某些方面,它却能超越领先的人工智能艺术生成器,如 Stable Diffusion 和 MidJourney。Perfusion 的主要新创意称为 “关键锁定”,这有助于避免过度拟合。英伟达目前只提交了研究论文,并承诺将很快发布代码。

消息来源:Decrypt
老王点评:真是令人吃惊的 AI 技术进展!似乎一夜之间,原本我们认为不可能做到的事情,都纷纷突破了限制出现了。

最高产的 Alpine Linux 打包者离开该项目

Alpine Linux 在容器和嵌入式领域得到了广泛应用,但令人遗憾的是,该 Linux 发行版软件包的最高产的维护者已决定离开。psykose 是过去一年中每个作者提交次数最多的人,她决定不再维护自己的软件包。她在过去一年中提交了 13,894 次,相比之下,第二多产的软件包维护者只有 2,053 次提交,而去年全年总提交次数是 26.8k。两天前,她最近提交的所有 alpinelinux/aports 都是在删除她负责的软件包。

消息来源:Phoronix
老王点评:她可能太累了。

Linus Torvalds 让大家禁用愚蠢的 AMD CPU 功能

Linus Torvalds 对最近困扰内核的 AMD fTPM 硬件随机数生成器问题感到沮丧,并表示希望禁用它。由 AMD fTPM 硬件随机数生成器引起的卡顿问题最初影响了 Windows 用户,但后来发现也影响了 Linux。修复程序已经上传到上游,并被移植到早期内核中,但一些与其相关的问题仍然令人头疼,一些用户仍在报告卡顿问题。Torvalds 在邮件列表上发表了自己的看法:“让我们禁用愚蠢的 fTPM 硬件随机数生成器吧”。

消息来源:Phoronix
老王点评:最初 AMD CPU 让 Torvalds 非常满意,但是现在一系列的不作为,让他终于忍不住发飙了。希望 AMD 能感受到 Torvalds 的怒火,尽快解决吧。

需要在虚拟机中访问 GRUB 菜单吗?以下是做法。

大多数现代虚拟机都配置为跳过 GRUB 引导加载程序 以获得无缝体验。

但是,你有时可能需要访问 GRUB 菜单。例如,如果你想切换回旧内核或进入恢复模式以 重置密码

? TLDR:重启虚拟机并在再次启动时按住 Shift 键。这将为你提供 GRUB 菜单。

在这篇简短的文章中,我将向你展示两种访问虚拟机中运行的 Linux 中的 GRUB 菜单的方法:

  • 临时方案(当你需要访问 GRUB 一两次时)
  • 永久方案(每次启动时都会显示 GRUB)

由于大多数用户不会每天与 GRUB 交互,因此我将从一个临时解决方案开始,你可以无需任何调整即可访问 GRUB。

? 我在此处的教程中使用了 Ubuntu,但这些步骤也适用于其他 Linux 发行版。

在虚拟机中访问 GRUB 引导加载程序(快速方式)

如果你偶尔想访问 GRUB,这应该是最好的方法,因为它不需要任何配置。

只需重新启动系统并按住 shift 键即可。

就是这样!

你将拥有没有任何时间限制的 GRUB 菜单:

Accessing grub menu in VM using shift key

很简单的方法。不是吗?

但它仅适用于特定的启动。那么如果你想在每次启动时都进入 GRUB 该怎么办呢? 请参考下面的方法。

永久在虚拟机中启用 GRUB 菜单(如果你愿意)

? 此方法需要在命令行中更改 GRUB 配置文件。请确保你能够轻松地在终端中进行编辑。

如果你需要处理 GRUB 菜单来访问其他操作系统或经常更改 从旧内核启动,那么此方法非常适合你。

要使 GRUB 在每次引导时都可访问,你必须在配置文件中进行更改。

首先,使用以下命令打开 GRUB 配置文件:

sudo nano /etc/default/grub

在这里,将 GRUB_TIMEOUT_STYLE=hidden 更改为 GRUB_TIMEOUT_STYLE=menu

change grub timeout style

接下来,在同一个配置文件中,指定你希望 GRUB 显示的秒数。

我建议 5 秒,因为它似乎在太长和太短之间取得了平衡(是的,非常相关):

GRUB_TIMEOUT=5

configure grub timeout in ubuntu

最后,你可以 保存更改并退出 nano 编辑器。

要激活对配置文件所做的更改,请使用以下命令更新 GRUB:

sudo update-grub

就是这样。重启系统,GRUB 应该会显示 5 秒钟。

将 GRUB 主题化如何?

大多数 Linux 发行版都会使用 GRUB 引导加载程序,因为它的配置非常简单,而且能完成工作。

但在默认情况下,除了黑色背景和纯文本外,它没什么样式。因此,我们制作了一份指南,教你如何让它看起来更漂亮:

定制 GRUB 以获得更好的体验

希望本指南对你有所帮助,如果你有任何疑问,请在评论中告诉我。

(题图:MJ/f75daf37-20c2-4bae-8a68-dc6a82ad0d61)


via: https://itsfoss.com/access-grub-virtual-machine/

作者:Sagar Sharma 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

进行单元测试可以提高代码质量,并且它不会打断你的工作流。

 title=

本文是 使用 CMake 和 VSCodium 设置一个构建系统 的后续文章。

在上一篇文章中我介绍了基于 VSCodiumCMake 配置构建系统。本文我将介绍如何通过 GoogleTestCTest 将单元测试集成到这个构建系统中。

首先克隆 这个仓库,用 VSCodium 打开,切换到 devops_2 标签。你可以通过点击 main 分支符号(红框处),然后选择 devops_2 标签(黄框处)来进行切换:

 title=

或者你可以通过命令行来切换:

$ git checkout tags/devops_2

GoogleTest

GoogleTest 是一个平台无关的开源 C++ 测试框架。单元测试是用来验证单个逻辑单元的行为的。尽管 GoogleTest 并不是专门用于单元测试的,我将用它对 Generator 库进行单元测试。

在 GoogleTest 中,测试用例是通过断言宏来定义的。断言可能产生以下结果:

  • 成功: 测试通过。
  • 非致命失败: 测试失败,但测试继续。
  • 致命失败: 测试失败,且测试终止。

致命断言和非致命断言通过不同的宏来区分:

  • ASSERT_*: 致命断言,失败时终止。
  • EXPECT_*: 非致命断言,失败时不终止。

谷歌推荐使用 EXPECT_* 宏,因为当测试中包含多个的断言时,它允许继续执行。断言有两个参数:第一个参数是测试分组的名称,第二个参数是测试自己的名称。Generator 只定义了 generate(...) 函数,所以本文中所有的测试都属于同一个测试组:GeneratorTest

针对 generate(...) 函数的测试可以从 GeneratorTest.cpp 中找到。

引用一致性检查

generate(...) 函数有一个 std::stringstream 的引用作为输入参数,并且它也将这个引用作为返回值。第一个测试就是检查输入的引用和返回的引用是否一致。

TEST(GeneratorTest, ReferenceCheck){
    const int NumberOfElements = 10;
    std::stringstream buffer;
    EXPECT_EQ(
        std::addressof(buffer),
        std::addressof(Generator::generate(buffer, NumberOfElements))
    );
}

在这个测试中我使用 std::addressof 来获取对象的地址,并用 EXPECT_EQ 来比较输入对象和返回对象是否是同一个。

检查元素个数

本测试检查作为输入的 std::stringstream 引用中的元素个数与输入参数中指定的个数是否相同。

TEST(GeneratorTest, NumberOfElements){
    const int NumberOfElements = 50;
    int nCalcNoElements = 0;

    std::stringstream buffer;

    Generator::generate(buffer, NumberOfElements);
    std::string s_no;

    while(std::getline(buffer, s_no, ' ')) {
        nCalcNoElements++;
    }

    EXPECT_EQ(nCalcNoElements, NumberOfElements);
}

乱序重排

本测试检查随机化引擎是否工作正常。如果连续调用两次 generate 函数,应该得到的是两个不同的结果。

TEST(GeneratorTest, Shuffle){

    const int NumberOfElements = 50;

    std::stringstream buffer_A;
    std::stringstream buffer_B;

    Generator::generate(buffer_A, NumberOfElements);
    Generator::generate(buffer_B, NumberOfElements);

    EXPECT_NE(buffer_A.str(), buffer_B.str());
}

求和校验

与前面的测试相比,这是一个大体量的测试。它检查 1 到 n 的数值序列的和与乱序重排后的序列的和是否相等。 generate(...) 函数应该生成一个 1 到 n 的乱序的序列,这个序列的和应当是不变的。

TEST(GeneratorTest, CheckSum){

    const int NumberOfElements = 50;
    int nChecksum_in = 0;
    int nChecksum_out = 0;

    std::vector<int> vNumbersRef(NumberOfElements); // Input vector
    std::iota(vNumbersRef.begin(), vNumbersRef.end(), 1); // Populate vector

    // Calculate reference checksum
    for(const int n : vNumbersRef){
        nChecksum_in += n;
    }

    std::stringstream buffer;
    Generator::generate(buffer, NumberOfElements);

    std::vector<int> vNumbersGen; // Output vector
    std::string s_no;

    // Read the buffer back back to the output vector
    while(std::getline(buffer, s_no, ' ')) {
        vNumbersGen.push_back(std::stoi(s_no));
    }

    // Calculate output checksum
    for(const int n : vNumbersGen){
        nChecksum_out += n;
    }

    EXPECT_EQ(nChecksum_in, nChecksum_out);
}

你可以像对一般 C++ 程序一样调试这些测试。

CTest

除了嵌入到代码中的测试之外,CTest 提供了可执行程序的测试方式。简而言之就是通过给可执行程序传入特定的参数,然后用 正则表达式 对它的输出进行匹配检查。通过这种方式可以很容易检查程序对于不正确的命令行参数的反应。这些测试定义在顶层的 CMakeLists.txt 文件中。下面我详细介绍 3 个测试用例:

参数正常

如果输入参数是一个正整数,程序应该输出应该是一个数列:

add_test(NAME RegularUsage COMMAND Producer 10)
set_tests_properties(RegularUsage
    PROPERTIES PASS_REGULAR_EXPRESSION "^[0-9 ]+"
)

没有提供参数

如果没有传入参数,程序应该立即退出并提示错误原因:

add_test(NAME NoArg COMMAND Producer)
set_tests_properties(NoArg
    PROPERTIES PASS_REGULAR_EXPRESSION "^Enter the number of elements as argument"
)

参数错误

当传入的参数不是整数时,程序应该退出并报错。比如给 Producer 传入参数 ABC

add_test(NAME WrongArg COMMAND Producer ABC)
set_tests_properties(WrongArg
    PROPERTIES PASS_REGULAR_EXPRESSION "^Error: Cannot parse"
)

执行测试

可以使用 ctest -R Usage -VV 命令来执行测试。这里给 ctest 的命令行参数:

  • -R <测试名称> : 执行单个测试
  • -VV:打印详细输出

测试执行结果如下:

$ ctest -R Usage -VV
UpdatecTest Configuration from :/home/stephan/Documents/cpp_testing sample/build/DartConfiguration.tcl
UpdateCTestConfiguration from :/home/stephan/Documents/cpp_testing sample/build/DartConfiguration.tcl
Test project /home/stephan/Documents/cpp_testing sample/build
Constructing a list of tests
Done constructing a list of tests
Updating test list for fixtures
Added 0 tests to meet fixture requirements
Checking test dependency graph...
Checking test dependency graph end

在这里我执行了名为 Usage 的测试。

它以无参数的方式调用 Producer

test 3
    Start 3: Usage
3: Test command: /home/stephan/Documents/cpp testing sample/build/Producer

输出不匹配 [^[0-9]+] 的正则模式,测试未通过。

3: Enter the number of elements as argument
1/1 test #3. Usage ................

Failed Required regular expression not found.
Regex=[^[0-9]+]

0.00 sec round.

0% tests passed, 1 tests failed out of 1
Total Test time (real) =
0.00 sec
The following tests FAILED:
3 - Usage (Failed)
Errors while running CTest
$

如果想要执行所有测试(包括那些用 GoogleTest 生成的),切换到 build 目录中,然后运行 ctest 即可:

 title=

在 VSCodium 中可以通过点击信息栏的黄框处来调用 CTest。如果所有测试都通过了,你会看到如下输出:

 title=

使用 Git 钩子进行自动化测试

目前为止,运行测试是开发者需要额外执行的步骤,那些不能通过测试的代码仍然可能被提交和推送到代码仓库中。利用 Git 钩子 可以自动执行测试,从而防止有瑕疵的代码被提交。

切换到 .git/hooks 目录,创建 pre-commit 文件,复制粘贴下面的代码:

#!/usr/bin/sh

(cd build; ctest --output-on-failure -j6)

然后,给文件增加可执行权限:

$ chmod +x pre-commit

这个脚本会在提交之前调用 CTest 进行测试。如果有测试未通过,提交过程就会被终止:

 title=

只有所有测试都通过了,提交过程才会完成:

 title=

这个机制也有一个漏洞:可以通过 git commit --no-verify 命令绕过测试。解决办法是配置构建服务器,这能保证只有正常工作的代码才能被提交,但这又是另一个话题了。

总结

本文提到的技术实施简单,并且能够帮你快速发现代码中的问题。做单元测试可以提高代码质量,同时也不会打断你的工作流。GoogleTest 框架提供了丰富的特性以应对各种测试场景,文中我所提到的只是一小部分而已。如果你想进一步了解 GoogleTest,我推荐你阅读 GoogleTest Primer

(题图:MJ/f212ce43-b60b-4005-b70d-8384f2ba5860)


via: https://opensource.com/article/22/1/unit-testing-googletest-ctest

作者:Stephan Avenwedde 选题:lujun9972 译者:toknow-gh 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出