分类 技术 下的文章

Python & Poetry on Fedora

Python 开发人员经常创建一个新的虚拟环境来分离项目依赖,然后用 pippipenv 等工具来管理它们。Poetry 是一个简化 Python 中依赖管理和打包的工具。这篇文章将向你展示如何在 Fedora 上使用 Poetry 来管理你的 Python 项目。

与其他工具不同,Poetry 只使用一个配置文件来进行依赖管理、打包和发布。这消除了对不同文件的需求,如 PipfileMANIFEST.insetup.py 等。这也比使用多个工具更快。

下面详细介绍一下开始使用 Poetry 时使用的命令。

在 Fedora 上安装 Poetry

如果你已经使用 Fedora 32 或以上版本,你可以使用这个命令直接从命令行安装 Poetry:

$ sudo dnf install poetry

编者注:在 Fedora Silverblue 或 CoreOs上,Python 3.9.2 是核心提交的一部分,你可以用下面的命令安装 Poetry:

rpm-ostree install poetry

初始化一个项目

使用 new 命令创建一个新项目:

$ poetry new poetry-project

用 Poetry 创建的项目结构是这样的:

├── poetry_project
│   └── init.py
├── pyproject.toml
├── README.rst
└── tests
    ├── init.py
    └── test_poetry_project.py

Poetry 使用 pyproject.toml 来管理项目的依赖。最初,这个文件看起来类似于这样:

[tool.poetry]
name = "poetry-project"
version = "0.1.0"
description = ""
authors = ["Kadermiyanyedi <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.9"

[tool.poetry.dev-dependencies]
pytest = "^5.2"

[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"

这个文件包含 4 个部分:

  • 第一部分包含描述项目的信息,如项目名称、项目版本等。
  • 第二部分包含项目的依赖。这些依赖是构建项目所必需的。
  • 第三部分包含开发依赖。
  • 第四部分描述的是符合 PEP 517 的构建系统。

如果你已经有一个项目,或者创建了自己的项目文件夹,并且你想使用 Poetry,请在你的项目中运行 init 命令。

$ poetry init

在这个命令之后,你会看到一个交互式的 shell 来配置你的项目。

创建一个虚拟环境

如果你想创建一个虚拟环境或激活一个现有的虚拟环境,请使用以下命令:

$ poetry shell

Poetry 默认在 /home/username/.cache/pypoetry 项目中创建虚拟环境。你可以通过编辑 Poetry 配置来更改默认路径。使用下面的命令查看配置列表:

$ poetry config --list

cache-dir = "/home/username/.cache/pypoetry"
virtualenvs.create = true
virtualenvs.in-project = true
virtualenvs.path = "{cache-dir}/virtualenvs"

修改 virtualenvs.in-project 配置变量,在项目目录下创建一个虚拟环境。Poetry 命令是:

$ poetry config virtualenv.in-project true

添加依赖

使用 poetry add 命令为项目安装一个依赖:

$ poetry add django

你可以使用带有 --dev 选项的 add 命令来识别任何只用于开发环境的依赖:

$ poetry add black --dev

add 命令会创建一个 poetry.lock 文件,用来跟踪软件包的版本。如果 poetry.lock 文件不存在,那么会安装 pyproject.toml 中所有依赖项的最新版本。如果 poetry.lock 存在,Poetry 会使用文件中列出的确切版本,以确保每个使用这个项目的人的软件包版本是一致的。

使用 poetry install 命令来安装当前项目中的所有依赖:

$ poetry install

通过使用 --no-dev 选项防止安装开发依赖:

$ poetry install --no-dev

列出软件包

show 命令会列出所有可用的软件包。--tree 选项将以树状列出软件包:

$ poetry show --tree

django 3.1.7 A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
├── asgiref >=3.2.10,<4
├── pytz *
└── sqlparse >=0.2.2

包含软件包名称,以列出特定软件包的详细信息:

$ poetry show requests

name         : requests
version      : 2.25.1
description  : Python HTTP for Humans.

dependencies
 - certifi >=2017.4.17
 - chardet >=3.0.2,<5
 - idna >=2.5,<3
 - urllib3 >=1.21.1,<1.27

最后,如果你想知道软件包的最新版本,你可以通过 --latest 选项:

$ poetry show --latest

idna     2.10      3.1    Internationalized Domain Names in Applications
asgiref  3.3.1     3.3.1  ASGI specs, helper code, and adapters

更多信息

Poetry 的更多详情可在文档中获取。


via: https://fedoramagazine.org/how-to-use-poetry-to-manage-your-python-projects-on-fedora/

作者:Kader Miyanyedi 选题:lujun9972 译者:geekpi 校对:wxy

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

抵制在 Git 中添加一些会增加管理难度的东西的冲动;这里有替代方法。

 title=

有权访问源代码使对安全性的分析以及应用程序的安全成为可能。但是,如果没有人真正看过代码,问题就不会被发现,即使人们主动地看代码,通常也要看很多东西。幸运的是,GitHub 拥有一个活跃的安全团队,最近,他们 发现了已提交到多个 Git 仓库中的特洛伊木马病毒,甚至仓库的所有者也偷偷溜走了。尽管我们无法控制其他人如何管理自己的仓库,但我们可以从他们的错误中吸取教训。为此,本文回顾了将文件添加到自己的仓库中的一些最佳实践。

了解你的仓库

 title=

这对于安全的 Git 仓库来可以说是头号规则。作为项目维护者,无论是你自己创建的还是采用别人的,你的工作是了解自己仓库中的内容。你可能无法记住代码库中每一个文件,但是你需要了解你所管理的内容的基本组成部分。如果在几十个合并后出现一个游离的文件,你会很容易地发现它,因为你不知道它的用途,你需要检查它来刷新你的记忆。发生这种情况时,请查看该文件,并确保准确了解为什么它是必要的。

禁止二进制大文件

 title=

Git 是为文本而生的,无论是用纯文本编写的 C 或 Python 还是 Java 文本,亦或是 JSON、YAML、XML、Markdown、HTML 或类似的文本。Git 对于二进制文件不是很理想。

两者之间的区别是:

$ cat hello.txt
This is plain text.
It's readable by humans and machines alike.
Git knows how to version this.

$ git diff hello.txt
diff --git a/hello.txt b/hello.txt
index f227cc3..0d85b44 100644
--- a/hello.txt
+++ b/hello.txt
@@ -1,2 +1,3 @@
 This is plain text.
+It's readable by humans and machines alike.
 Git knows how to version this.

$ git diff pixel.png
diff --git a/pixel.png b/pixel.png
index 563235a..7aab7bc 100644
Binary files a/pixel.png and b/pixel.png differ

$ cat pixel.png
�PNG
▒
IHDR7n�$gAMA��
              �abKGD݊�tIME�

                          -2R��
IDA�c`�!�3%tEXtdate:create2020-06-11T11:45:04+12:00��r.%tEXtdate:modify2020-06-11T11:45:04+12:00��ʒIEND�B`�

二进制文件中的数据不能像纯文本一样被解析,因此,如果二进制文件发生任何更改,则必须重写整个内容。一个版本与另一个版本之间唯一的区别就是全部不同,这会快速增加仓库大小。

更糟糕的是,Git 仓库维护者无法合理地审计二进制数据。这违反了头号规则:应该对仓库的内容了如指掌。

除了常用的 POSIX 工具之外,你还可以使用 git diff 检测二进制文件。当你尝试使用 --numstat 选项来比较二进制文件时,Git 返回空结果:

$ git diff --numstat /dev/null pixel.png | tee
-     -   /dev/null => pixel.png
$ git diff --numstat /dev/null file.txt | tee
5788  0   /dev/null => list.txt

如果你正在考虑将二进制大文件(BLOB)提交到仓库,请停下来先思考一下。如果它是二进制文件,那它是由什么生成的。是否有充分的理由不在构建时生成它们,而是将它们提交到仓库?如果你认为提交二进制数据是有意义的,请确保在 README 文件或类似文件中指明二进制文件的位置、为什么是二进制文件的原因以及更新它们的协议是什么。必须谨慎对其更新,因为你每提交一个二进制大文件的变化,它的存储空间实际上都会加倍。

让第三方库留在第三方

第三方库也不例外。尽管它是开源的众多优点之一,你可以不受限制地重用和重新分发不是你编写的代码,但是有很多充分的理由不把第三方库存储在你自己的仓库中。首先,除非你自己检查了所有代码(以及将来的合并),否则你不能为第三方完全担保。其次,当你将第三方库复制到你的 Git 仓库中时,会将焦点从真正的上游源代码中分离出来。从技术上讲,对库有信心的人只对该库的主副本有把握,而不是对随机仓库的副本有把握。如果你需要锁定特定版本的库,请给开发者提供一个合理的项目所需的发布 URL,或者使用 Git 子模块

抵制盲目的 git add

 title=

如果你的项目已编译,请抵制住使用 git add . 的冲动(其中 . 是当前目录或特定文件夹的路径),因为这是一种添加任何新东西的简单方法。如果你不是手动编译项目,而是使用 IDE 为你管理项目,这一点尤其重要。用 IDE 管理项目时,跟踪添加到仓库中的内容会非常困难,因此仅添加你实际编写的内容非常重要,而不是添加项目文件夹中出现的任何新对象。

如果你使用了 git add .,请在推送之前检查暂存区里的内容。如果在运行 make clean 或等效命令后,执行 git status 时在项目文件夹中看到一个陌生的对象,请找出它的来源,以及为什么仍然在项目的目录中。这是一种罕见的构建工件,不会在编译期间重新生成,因此在提交前请三思。

使用 Git ignore

 title=

许多为程序员打造的便利也非常杂乱。任何项目的典型项目目录,无论是编程的,还是艺术的或其他的,到处都是隐藏的文件、元数据和遗留的工件。你可以尝试忽略这些对象,但是 git status 中的提示越多,你错过某件事的可能性就越大。

你可以通过维护一个良好的 gitignore 文件来为你过滤掉这种噪音。因为这是使用 Git 的用户的共同要求,所以有一些入门级的 gitignore 文件。Github.com/github/gitignore 提供了几个专门创建的 gitignore 文件,你可以下载这些文件并将其放置到自己的项目中,Gitlab.com 在几年前就将gitignore 模板集成到了仓库创建工作流程中。使用这些模板来帮助你为项目创建适合的 gitignore 策略并遵守它。

查看合并请求

 title=

当你通过电子邮件收到一个合并/拉取请求或补丁文件时,不要只是为了确保它能正常工作而进行测试。你的工作是阅读进入代码库的新代码,并了解其是如何产生结果的。如果你不同意这个实现,或者更糟的是,你不理解这个实现,请向提交该实现的人发送消息,并要求其进行说明。质疑那些希望成为版本库永久成员的代码并不是一种社交失误,但如果你不知道你把什么合并到用户使用的代码中,那就是违反了你和用户之间的社交契约。

Git 责任

社区致力于开源软件良好的安全性。不要鼓励你的仓库中不良的 Git 实践,也不要忽视你克隆的仓库中的安全威胁。Git 功能强大,但它仍然只是一个计算机程序,因此要以人为本,确保每个人的安全。


via: https://opensource.com/article/20/7/git-repos-best-practices

作者:Seth Kenlon 选题:lujun9972 译者:stevenzdg988 校对:wxy

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

就我记忆所及,我一直是 Ubuntu 的用户。我曾经转向过其他发行版,但最终还是一次次回到 Ubuntu。但最近,我开始使用 openSUSE 来尝试一些非 Debian 的东西。

随着我对 openSUSE 的不断探索,我不断发现 SUSE 中略有不同的东西,并打算在教程中介绍它们。

第一篇我写的是更新 openSUSE 系统。有两种方法可以做到:

  • 使用终端(适用于 openSUSE 桌面和服务器)
  • 使用图形工具(适用于 openSUSE 桌面)

通过命令行更新 openSUSE

更新 openSUSE 的最简单方法是使用 zypper 命令。它提供了补丁和更新管理的全部功能。它可以解决文件冲突和依赖性问题。更新也包括 Linux 内核。

如果你正在使用 openSUSE Leap,请使用这个命令:

sudo zypper update

你也可以用 up 代替 update,但我觉得 update 更容易记住。

如果你正在使用 openSUSE Tumbleweed,请使用 dist-upgrade 或者 dup(简称)。Tumbleweed 是滚动发行版,因此建议使用 dist-upgrade 选项。

sudo zypper dist-upgrade

它将显示要升级、删除或安装的软件包列表。

如果你的系统需要重启,你会得到通知。

如果你只是想刷新仓库(像 sudo apt update 一样),你可以使用这个命令:

sudo zypper refresh

如果你想列出可用的更新,也可以这样做:

sudo zypper list-updates

以图形方式更新 openSUSE

如果你使用 openSUSE 作为桌面,你可以选择使用 GUI 工具来安装更新。这个工具可能会根据 你使用的桌面环境 而改变。

例如,KDE 有自己的软件中心,叫做 “Discover”。你可以用它来搜索和安装新的应用。你也可以用它来安装系统更新。

事实上,KDE 会在通知区通知你可用的系统更新。你必须打开 Discover,因为点击通知不会自动进入 Discover。

如果你觉得这很烦人,你可以使用这些命令禁用它:

sudo zypper remove plasma5-pk-updates
sudo zypper addlock plasma5-pk-updates

不过我不推荐。最好是获取可用的更新通知。

还有一个 YAST 软件管理 GUI 工具,你可以用它来对软件包管理进行更精细的控制。

就是这些了。这是一篇简短的文章。在下一篇 SUSE 教程中,我将通过实例向大家展示一些常用的 zypper 命令。敬请期待。


via: https://itsfoss.com/update-opensuse/

作者:Abhishek Prakash 选题:lujun9972 译者:geekpi 校对:wxy

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

到底什么是 WebAssembly?

WebAssembly,也叫 Wasm,是一种为 Web 优化的代码格式和 API(应用编程接口),它可以大大提高网站的性能和能力。WebAssembly 的 1.0 版本于 2017 年发布,并于 2019 年成为 W3C 官方标准。

该标准得到了所有主流浏览器供应商的积极支持,原因显而易见:官方列出的 “浏览器内部”用例 中提到了,其中包括视频编辑、3D 游戏、虚拟和增强现实、p2p 服务和科学模拟。除了让浏览器的功能比JavaScript 强大得多,该标准甚至可以延长网站的寿命:例如,正是 WebAssembly 为 互联网档案馆的 Flash 动画和游戏 提供了持续的支持。

不过,WebAssembly 并不只用于浏览器,目前它还被用于移动和基于边缘环境的 Cloudflare Workers 等产品中。

WebAssembly 如何工作?

.wasm 格式的文件包含低级二进制指令(字节码),可由使用通用栈的虚拟机以“接近 CPU 原生速度”执行。这些代码被打包成模块(可以被浏览器直接执行的对象),每个模块可以被一个网页多次实例化。模块内部定义的函数被列在一个专用数组中,或称为 Table ,相应的数据被包含在另一个结构中,称为 缓存数组 arraybuffer 。开发者可以通过 Javascript WebAssembly.memory() 的调用,为 .wasm 代码显式分配内存。

.wasm 格式也有纯文本版本,它可以大大简化学习和调试。然而,WebAssembly 并不是真的要供人直接使用。从技术上讲,.wasm 只是一个与浏览器兼容的编译目标:一种用高级编程语言编写的软件编译器可以自动翻译的代码格式。

这种选择正是使开发人员能够使用数十亿人熟悉的语言(C/C++、Python、Go、Rust 等)直接为用户界面进行编程的方式,但以前浏览器无法对其进行有效利用。更妙的是,至少在理论上程序员可以利用它们,无需直接查看 WebAssembly 代码,也无需担心物理 CPU 实际运行他们的代码(因为目标是一个虚拟机)。

但是我们已经有了 JavaScript,我们真的需要 WebAssembly 吗?

是的,有几个原因。首先,作为二进制指令,.wasm 文件比同等功能的 JavaScript 文件小得多,下载速度也快得多。最重要的是,Javascript 文件必须在浏览器将其转换为其内部虚拟机可用的字节码之前进行完全解析和验证。

而 .wasm 文件则可以一次性验证和编译,从而使“流式编译”成为可能:浏览器在开始下载它们的那一刻就可以开始编译和执行它们,就像串流电影一样。

这就是说,并不是所有可以想到的 WebAssembly 应用都肯定会比由专业程序员手动优化的等效 JavaScript 应用更快或更小。例如,如果一些 .wasm 需要包含 JavaScript 不需要的库,这种情况可能会发生。

WebAssembly 是否会让 JavaScript 过时?

一句话:不会。暂时不会,至少在浏览器内不会。WebAssembly 模块仍然需要 JavaScript,因为在设计上它们不能访问文档对象模型 (DOM)—— 主要用于修改网页的 API。此外,.wasm 代码不能进行系统调用或读取浏览器的内存。WebAssembly 只能在沙箱中运行,一般来说,它能与外界的交互甚至比 JavaScript 更少,而且只能通过 JavaScript 接口进行。

因此,至少在不久的将来 .wasm 模块将只是通过 JavaScript 提供那些如果用 JavaScript 语言编写会消耗更多带宽、内存或 CPU 时间的部分。

Web 浏览器如何运行 WebAssembly?

一般来说,浏览器至少需要两块来处理动态应用:运行应用代码的虚拟机(VM),以及可以同时修改浏览器行为和网页显示的 API。

现代浏览器内部的虚拟机通过以下方式同时支持 JavaScript 和 WebAssembly:

  1. 浏览器下载一个用 HTML 标记语言编写的网页,然后进行渲染
  2. 如果该 HTML 调用 JavaScript 代码,浏览器的虚拟机就会执行该代码。但是...
  3. 如果 JavaScript 代码中包含了 WebAssembly 模块的实例,那么就按照上面的描述获取该实例,然后根据需要通过 JavaScript 的 WebAssembly API 来使用该实例
  4. 当 WebAssembly 代码产生的东西将修改 DOM(即“宿主”网页)的结构,JavaScript 代码就会接收到,并继续进行实际的修改。

我如何才能创建可用的 WebAssembly 代码?

越来越多的编程语言社区支持直接编译到 Wasm,我们建议从 webassembly.org入门指南 开始,这取决于你使用什么语言。请注意,并不是所有的编程语言都有相同水平的 Wasm 支持,因此你的工作量可能会有所不同。

我们计划在未来几个月内发布一系列文章,提供更多关于 WebAssembly 的信息。要自己开始使用它,你可以报名参加 Linux 基金会的免费 WebAssembly 介绍在线培训课程。

这篇WebAssembly 介绍首次发布在 Linux Foundation – Training


via: https://www.linux.com/news/an-introduction-to-webassembly/

作者:Dan Brown 选题:lujun9972 译者:geekpi 校对:wxy

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

Bash 自动测试系统可以使 Bash 代码也通过 Java、Ruby 和 Python 开发人员所使用的同类测试过程。

用 Java、Ruby 和 Python 等语言编写应用程序的软件开发人员拥有复杂的库,可以帮助他们随着时间的推移保持软件的完整性。他们可以创建测试,以在结构化环境中通过执行一系列动作来运行应用程序,以确保其软件所有的方面均按预期工作。

当这些测试在持续集成(CI)系统中自动进行时,它们的功能就更加强大了,每次推送到源代码库都会触发测试,并且在测试失败时会立即通知开发人员。这种快速反馈提高了开发人员对其应用程序功能完整性的信心。

Bash 自动测试系统 Bash Automated Testing System BATS)使编写 Bash 脚本和库的开发人员能够将 Java、Ruby、Python 和其他开发人员所使用的相同惯例应用于其 Bash 代码中。

安装 BATS

BATS GitHub 页面包含了安装指令。有两个 BATS 辅助库提供更强大的断言或允许覆写 BATS 使用的 Test Anything Protocol(TAP)输出格式。这些库可以安装在一个标准位置,并被所有的脚本引用。更方便的做法是,将 BATS 及其辅助库的完整版本包含在 Git 仓库中,用于要测试的每组脚本或库。这可以通过 git 子模块 系统来完成。

以下命令会将 BATS 及其辅助库安装到 Git 知识库中的 test 目录中。

git submodule init
git submodule add https://github.com/sstephenson/bats test/libs/bats
git submodule add https://github.com/ztombol/bats-assert test/libs/bats-assert
git submodule add https://github.com/ztombol/bats-support test/libs/bats-support
git add .
git commit -m 'installed bats'

要克隆 Git 仓库并同时安装其子模块,请在 git clone 时使用 --recurse-submodules 标记。

每个 BATS 测试脚本必须由 bats 可执行文件执行。如果你将 BATS 安装到源代码仓库的 test/libs 目录中,则可以使用以下命令调用测试:

./test/libs/bats/bin/bats <测试脚本的路径>

或者,将以下内容添加到每个 BATS 测试脚本的开头:

#!/usr/bin/env ./test/libs/bats/bin/bats
load 'libs/bats-support/load'
load 'libs/bats-assert/load'

并且执行命令 chmod +x <测试脚本的路径>。 这将 a、使它们可与安装在 ./test/libs/bats 中的 BATS 一同执行,并且 b、包含这些辅助库。BATS 测试脚本通常存储在 test 目录中,并以要测试的脚本命名,扩展名为 .bats。例如,一个测试 bin/build 的 BATS 脚本应称为 test/build.bats

你还可以通过向 BATS 传递正则表达式来运行一整套 BATS 测试文件,例如 ./test/lib/bats/bin/bats test/*.bats

为 BATS 覆盖率而组织库和脚本

Bash 脚本和库必须以一种有效地方式将其内部工作原理暴露给 BATS 进行组织。通常,在调用或执行时库函数和运行诸多命令的 Shell 脚本不适合进行有效的 BATS 测试。

例如,build.sh 是许多人都会编写的典型脚本。本质上是一大堆代码。有些人甚至可能将这堆代码放入库中的函数中。但是,在 BATS 测试中运行一大堆代码,并在单独的测试用例中覆盖它可能遇到的所有故障类型是不可能的。测试这堆代码并有足够的覆盖率的唯一方法就是把它分解成许多小的、可重用的、最重要的是可独立测试的函数。

向库添加更多的函数很简单。额外的好处是其中一些函数本身可以变得出奇的有用。将库函数分解为许多较小的函数后,你可以在 BATS 测试中 援引 source 这些库,并像测试任何其他命令一样运行这些函数。

Bash 脚本也必须分解为多个函数,执行脚本时,脚本的主要部分应调用这些函数。此外,还有一个非常有用的技巧,可以让你更容易地用 BATS 测试 Bash 脚本:将脚本主要部分中执行的所有代码都移到一个函数中,称为 run_main。然后,将以下内容添加到脚本的末尾:

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]
then
  run_main
fi

这段额外的代码做了一些特别的事情。它使脚本在作为脚本执行时与使用 援引 source 进入环境时的行为有所不同。通过援引并测试单个函数,这个技巧使得脚本的测试方式和库的测试方式变得一样。例如,这是重构的 build.sh,以获得更好的 BATS 可测试性

编写和运行测试

如上所述,BATS 是一个 TAP 兼容的测试框架,其语法和输出对于使用过其他 TAP 兼容测试套件(例如 JUnit、RSpec 或 Jest)的用户来说将是熟悉的。它的测试被组织成单个测试脚本。测试脚本被组织成一个或多个描述性 @test 块中,它们描述了被测试应用程序的单元。每个 @test 块将运行一系列命令,这些命令准备测试环境、运行要测试的命令,并对被测试命令的退出和输出进行断言。许多断言函数是通过 batsbats-assertbats-support 库导入的,这些库在 BATS 测试脚本的开头加载到环境中。下面是一个典型的 BATS 测试块:

@test "requires CI_COMMIT_REF_SLUG environment variable" {
  unset CI_COMMIT_REF_SLUG
  assert_empty "${CI_COMMIT_REF_SLUG}"
  run some_command
  assert_failure
  assert_output --partial "CI_COMMIT_REF_SLUG"
}

如果 BATS 脚本包含 setup(安装)和/或 teardown(拆卸) 函数,则 BATS 将在每个测试块运行之前和之后自动执行它们。这样就可以创建环境变量、测试文件以及执行一个或所有测试所需的其他操作,然后在每次测试运行后将其拆卸。Build.bats 是对我们新格式化的 build.sh 脚本的完整 BATS 测试。(此测试中的 mock_docker 命令将在以下关于模拟/打标的部分中进行说明。)

当测试脚本运行时,BATS 使用 exec(执行)来将每个 @test 块作为单独的子进程运行。这样就可以在一个 @test 中导出环境变量甚至函数,而不会影响其他 @test 或污染你当前的 Shell 会话。测试运行的输出是一种标准格式,可以被人理解,并且可以由 TAP 使用端以编程方式进行解析或操作。下面是 CI_COMMIT_REF_SLUG 测试块失败时的输出示例:

 ✗ requires CI_COMMIT_REF_SLUG environment variable
   (from function `assert_output' in file test/libs/bats-assert/src/assert.bash, line 231,
    in test file test/ci_deploy.bats, line 26)
     `assert_output --partial "CI_COMMIT_REF_SLUG"' failed

   -- output does not contain substring --
   substring (1 lines):
     CI_COMMIT_REF_SLUG
   output (3 lines):
     ./bin/deploy.sh: join_string_by: command not found
     oc error
     Could not login
   --

   ** Did not delete , as test failed **

1 test, 1 failure

下面是成功测试的输出:

✓ requires CI_COMMIT_REF_SLUG environment variable

辅助库

像任何 Shell 脚本或库一样,BATS 测试脚本可以包括辅助库,以在测试之间共享通用代码或增强其性能。这些辅助库,例如 bats-assertbats-support 甚至可以使用 BATS 进行测试。

库可以和 BATS 脚本放在同一个测试目录下,如果测试目录下的文件数量过多,也可以放在 test/libs 目录下。BATS 提供了 load 函数,该函数接受一个相对于要测试的脚本的 Bash 文件的路径(例如,在我们的示例中的 test),并援引该文件。文件必须以后缀 .bash 结尾,但是传递给 load 函数的文件路径不能包含后缀。build.bats 加载 bats-assertbats-support 库、一个小型 helpers.bash 库以及 docker_mock.bash 库(如下所述),以下代码位于测试脚本的开头,解释器魔力行下方:

load 'libs/bats-support/load'
load 'libs/bats-assert/load'
load 'helpers'
load 'docker_mock'

打标测试输入和模拟外部调用

大多数 Bash 脚本和库运行时都会执行函数和/或可执行文件。通常,它们被编程为基于这些函数或可执行文件的输出状态或输出(stdoutstderr)以特定方式运行。为了正确地测试这些脚本,通常需要制作这些命令的伪版本,这些命令被设计成在特定测试过程中以特定方式运行,称为“ 打标 stubbing ”。可能还需要监视正在测试的程序,以确保其调用了特定命令,或者使用特定参数调用了特定命令,此过程称为“ 模拟 mocking ”。有关更多信息,请查看在 Ruby RSpec 中 有关模拟和打标的讨论,它适用于任何测试系统。

Bash shell 提供了一些技巧,可以在你的 BATS 测试脚本中使用这些技巧进行模拟和打标。所有这些都需要使用带有 -f 标志的 Bash export 命令来导出一个覆盖了原始函数或可执行文件的函数。必须在测试程序执行之前完成此操作。下面是重写可执行命令 cat 的简单示例:

function cat() { echo "THIS WOULD CAT ${*}" }
export -f cat

此方法以相同的方式覆盖了函数。如果一个测试需要覆盖要测试的脚本或库中的函数,则在对函数进行打标或模拟之前,必须先声明已测试脚本或库,这一点很重要。否则,在声明脚本时,打标/模拟将被原函数替代。另外,在运行即将进行的测试命令之前确认打标/模拟。下面是build.bats 的示例,该示例模拟 build.sh 中描述的raise 函数,以确保登录函数会引发特定的错误消息:

@test ".login raises on oc error" {
  source ${profile_script}
  function raise() { echo "${1} raised"; }
  export -f raise
  run login
  assert_failure
  assert_output -p "Could not login raised"
}

一般情况下,没有必要在测试后复原打标/模拟的函数,因为 export(输出)仅在当前 @test 块的 exec(执行)期间影响当前子进程。但是,可以模拟/打标 BATS assert 函数在内部使用的命令(例如 catsed 等)是可能的。在运行这些断言命令之前,必须对这些模拟/打标函数进行 unset(复原),否则它们将无法正常工作。下面是 build.bats 中的一个示例,该示例模拟 sed,运行 build_deployable 函数并在运行任何断言之前复原 sed

@test ".build_deployable prints information, runs docker build on a modified Dockerfile.production and publish_image when its not a dry_run" {
  local expected_dockerfile='Dockerfile.production'
  local application='application'
  local environment='environment'
  local expected_original_base_image="${application}"
  local expected_candidate_image="${application}-candidate:${environment}"
  local expected_deployable_image="${application}:${environment}"
  source ${profile_script}
  mock_docker build --build-arg OAUTH_CLIENT_ID --build-arg OAUTH_REDIRECT --build-arg DDS_API_BASE_URL -t "${expected_deployable_image}" -
  function publish_image() { echo "publish_image ${*}"; }
  export -f publish_image
  function sed() {
    echo "sed ${*}" >&2;
    echo "FROM application-candidate:environment";
  }
  export -f sed
  run build_deployable "${application}" "${environment}"
  assert_success
  unset sed
  assert_output --regexp "sed.*${expected_dockerfile}"
  assert_output -p "Building ${expected_original_base_image} deployable ${expected_deployable_image} FROM ${expected_candidate_image}"
  assert_output -p "FROM ${expected_candidate_image} piped"
  assert_output -p "build --build-arg OAUTH_CLIENT_ID --build-arg OAUTH_REDIRECT --build-arg DDS_API_BASE_URL -t ${expected_deployable_image} -"
  assert_output -p "publish_image ${expected_deployable_image}"
}

有的时候相同的命令,例如 foo,将在被测试的同一函数中使用不同的参数多次调用。这些情况需要创建一组函数:

  • mock_foo:将期望的参数作为输入,并将其持久化到 TMP 文件中
  • foo:命令的模拟版本,该命令使用持久化的预期参数列表处理每个调用。必须使用 export -f 将其导出。
  • cleanup_foo:删除 TMP 文件,用于拆卸函数。这可以进行测试以确保在删除之前成功完成 @test 块。

由于此功能通常在不同的测试中重复使用,因此创建一个可以像其他库一样加载的辅助库会变得有意义。

docker\_mock.bash 是一个很棒的例子。它被加载到 build.bats 中,并在任何测试调用 Docker 可执行文件的函数的测试块中使用。使用 docker_mock 典型的测试块如下所示:

@test ".publish_image fails if docker push fails" {
  setup_publish
  local expected_image="image"
  local expected_publishable_image="${CI_REGISTRY_IMAGE}/${expected_image}"
  source ${profile_script}
  mock_docker tag "${expected_image}" "${expected_publishable_image}"
  mock_docker push "${expected_publishable_image}" and_fail
  run publish_image "${expected_image}"
  assert_failure
  assert_output -p "tagging ${expected_image} as ${expected_publishable_image}"
  assert_output -p "tag ${expected_image} ${expected_publishable_image}"
  assert_output -p "pushing image to gitlab registry"
  assert_output -p "push ${expected_publishable_image}"
}

该测试建立了一个使用不同的参数两次调用 Docker 的预期。在对Docker 的第二次调用失败时,它会运行测试命令,然后测试退出状态和对 Docker 调用的预期。

一方面 BATS 利用 mock_docker.bash 引入 ${BATS_TMPDIR} 环境变量,BATS 在测试开始的位置对其进行了设置,以允许测试和辅助程序在标准位置创建和销毁 TMP 文件。如果测试失败,mock_docker.bash 库不会删除其持久化的模拟文件,但会打印出其所在位置,以便可以查看和删除它。你可能需要定期从该目录中清除旧的模拟文件。

关于模拟/打标的一个注意事项:build.bats 测试有意识地违反了关于测试声明的规定:不要模拟没有拥有的! 该规定要求调用开发人员没有编写代码的测试命令,例如 dockercatsed 等,应封装在自己的库中,应在使用它们脚本的测试中对其进行模拟。然后应该在不模拟外部命令的情况下测试封装库。

这是一个很好的建议,而忽略它是有代价的。如果 Docker CLI API 发生变化,则测试脚本不会检测到此变化,从而导致错误内容直到经过测试的 build.sh 脚本在使用新版本 Docker 的生产环境中运行后才显示出来。测试开发人员必须确定要严格遵守此标准的程度,但是他们应该了解其所涉及的权衡。

总结

在任何软件开发项目中引入测试制度,都会在以下两方面产生权衡: a、增加开发和维护代码及测试所需的时间和组织,b、增加开发人员在对应用程序整个生命周期中完整性的信心。测试制度可能不适用于所有脚本和库。

通常,满足以下一个或多个条件的脚本和库才可以使用 BATS 测试:

  • 值得存储在源代码管理中
  • 用于关键流程中,并依靠它们长期稳定运行
  • 需要定期对其进行修改以添加/删除/修改其功能
  • 可以被其他人使用

一旦决定将测试规则应用于一个或多个 Bash 脚本或库,BATS 就提供其他软件开发环境中可用的全面测试功能。

致谢:感谢 Darrin Mann 向我引荐了 BATS 测试。


via: https://opensource.com/article/19/2/testing-bash-bats

作者:Darin London 选题:lujun9972 译者:stevenzdg988 校对:wxy

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

基于 Linux 的 Moodle 学习管理系统进行远程教学。

 title=

这次大流行对远程教育的需求比以往任何时候都更大。使得像 Moodle 这样的 学习管理系统 learning management system (LMS)比以往任何时候都重要,因为越来越多的学校教育是借助虚拟现实技术的提供。

Moodle 是用 PHP 编写的免费 LMS,并以开源 GNU 公共许可证(GPL)分发。它是由 Martin Dougiamas 开发的,自 2002 年发布以来一直在不断发展。Moodle 可用于混合学习、远程学习、 翻转课堂 flipped classroom 和其他形式的在线学习。目前,全球有超过 1.9 亿用户 和 145,000 个注册的 Moodle 网站。

我曾作为 Moodle 管理员、教师和学生等角色使用过 Moodle,在本文中,我将向你展示如何设置并开始使用它。

在 Linux 系统上安装 Moodle

Moodle 对 系统要求 适中,并且有大量文档可为你提供帮助。我最喜欢的安装方法是从 Turnkey Linux 下载并制作 ISO,然后在 VirtualBox 中安装 Moodle 网站。

首先,下载 Moodle ISO 保存到电脑中。

下一步,安装 VirtualBox 的 Linux 命令行如下:

$ sudo apt install virtualbox

或,

$ sudo dnf install virtualbox

当下载完成后,启动 VirtualBox 并在控制台中选择“ 新建 New ”按钮。

 title=

选择使用的虚拟机的名称、操作系统(Linux)和 Linux 类型(例如 Debian 64 位)。

 title=

下一步,配置虚拟机内存大小,使用默认值 1024 MB。接下来选择 “ 动态分配 dynamically allocated ”虚拟磁盘并在虚拟机中添加 Moodle.iso 镜像。

 title=

将你的网络设置从 NAT 更改为 “ 桥接模式 Bridged adapter ”。然后启动虚拟机并安装 ISO 以创建 Moodle 虚拟机。在安装过程中,系统将提示为 root 帐户、MySQL 和Moodle 创建密码。Moodle 密码必须至少包含八个字符,至少一个大写字母和至少一个特殊字符。

重启虚拟机。安装完成后,请确保将 Moodle 应用配置内容记录在安全的地方。(安装后,可以根据需要删除 ISO 文件。)

 title=

重要提示,在互联网上的任何人还看不到你的 Moodle 实例。它仅存在于你的本地网络中:现在只有建筑物中与你连接到相同的路由器或 wifi 接入点的人可以访问你的站点。全世界的互联网无法连接到它,因为你位于防火墙(可能嵌入在路由器中,还可能嵌入在计算机中)的后面。有关网络配置的更多信息,请阅读 Seth Kenlon 关于 打开端口和通过防火墙进行流量路由 的文章。

开始使用 Moodle

现在你可以登录到 Moodle 机器并熟悉该软件了。使用默认的用户名 admin 和创建 Moodle VM 时设置的密码登录 Moodle。

 title=

首次登录后,你将看到初始的 Moodle 网站的主仪表盘。

 title=

默认的应用名称是 “Turnkey Moodle”,但是可以很容易地对其进行更改以适合你的学校、课堂或其他需要和选择。要使你的 Moodle 网站个性化,请在用户界面左侧的菜单中,选择“站点首页Site home”。然后,点击屏幕右侧的 “ 设置 Settings ” 图标,然后选择 “ 编辑设置 Edit settings ”。

 title=

你可以根据需要更改站点名称,并添加简短名称和站点描述。

 title=

确保滚动到底部并保存更改。现在,你的网站已定制好。

 title=

默认类别为其他,这不会帮助人们识别你网站的目的。要添加类别,请返回主仪表盘,然后从左侧菜单中选择 “ 站点管理 Site administration ”。 在 “ 课程 Courses ”下,选择 “ 添加类别 Add a category ”并输入有关你的网站的详细信息。

 title=

要添加课程,请返回 “ 站点管理 Site administration ”,然后单击 “ 添加新课程 Add a new course ”。你将看到一系列选项,例如为课程命名、提供简短名称、设定类别以及设置课程的开始和结束日期。你还可以为课程形式设置选项,例如社交、每周式课程、主题,以及其外观、文件上传大小、完成情况跟踪等等。

 title=

添加和管理用户

现在,你已经设置了课程,你可以添加用户。有多种方法可以做到这一点。如果你是家庭教师,则手动输入是一个不错的开始。Moodle 支持基于电子邮件的注册、LDAPShibboleth(口令或暗语) 和许多其他方式等。校区和其他较大的机构可以用逗号分隔的文件上传用户。也可以批量添加密码,并在首次登录时强制更改密码。有关更多信息,一定要查阅 Moodle 文档

Moodle 是一个非常细化的、面向许可的环境。使用 Moodle 的菜单将策略和角色分配给用户并执行这些分配很容易。

Moodle 中有许多角色,每个角色都有特定的特权和许可。默认角色有管理员、课程创建者、教师、非编辑教师、学生、来宾和经过身份验证的用户,但你可以添加其他角色。

为课程添加内容

一旦搭建了 Moodle 网站并设置了课程,就可以向课程中添加内容。Moodle 拥有创建出色内容所需要的所有工具,并且它建立在强调 社会建构主义 观点的坚实教学法之上。

我创建了一个名为 “Code with Mu” 的示例课程。它在 “ 编程 Programming ” 类别和 “Python” 子类别中。

 title=

我为课程选择了每周式课程,默认为四个星期。使用编辑工具,我隐藏了除课程第一周以外的所有内容。这样可以确保我的学生始终专注于材料。

作为教师或 Moodle 管理员,我可以通过单击 “ 添加活动或资源 Add an activity or resource ” 来将活动添加到每周的教学中。

 title=

我会看到一个弹出窗口,其中包含可以分配给我的学生的各种活动。

 title=

Moodle 的工具和活动使我可以轻松地创建学习材料,并以一个简短的测验来结束一周的学习。

 title=

你可以使用 1600 多个插件来扩展 Moodle,包括新的活动、问题类型,与其他系统的集成等等。例如,BigBlueButton 插件支持幻灯片共享、白板、音频和视频聊天以及分组讨论。其他值得考虑的包括用于视频会议的 Jitsi 插件、抄袭检查器 和用于颁发徽章的 开放徽章工厂

继续探索 Moodle

Moodle 是一个功能强大的 LMS,我希望此介绍能引起你的兴趣,以了解更多信息。有很多出色的 指南 可以帮助你提高技能,如果想要查看 Moodle 的内容,可以在其 演示站点 上查看运行中的 Moodle;如果你想了解 Moodle 的底层结构或为开发做出 贡献,也可以访问 Moodle 的源代码。如果你喜欢在旅途中工作,Moodle 也有一款出色的 移动应用,适用于 iOS 和 Android。在 TwitterFacebookLinkedIn 上关注 Moodle,以了解最新消息。


via: https://opensource.com/article/20/10/moodle

作者:Don Watkins 选题:lujun9972 译者:stevenzdg988 校对:wxy

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