1.测试脚手架
在本新手教程中,我们打算为etcd编写一个测试。etcd是一个分布式共识系统。在此,我想建议各位在学习过程中能自己亲手敲一下代码,即便一开始还不是特别理解所有内容。如此一来既能帮你学得更快,也不会在我们开始修改更复杂函数代码时而感到茫然。
我们首先在任意目录下创建一个新的Leiningen(音读['laɪnɪŋən])项目。
$ lein new jepsen.etcdemo
Generating a project called jepsen.etcdemo based on the 'default' template.
The default template is intended for library projects, not applications.
To see other templates (app, plugin, etc), try `lein help new`.
$ cd jepsen.etcdemo
$ ls
CHANGELOG.md doc/ LICENSE project.clj README.md resources/ src/ test/正如任何一个新创建的Clojure(音读/ˈkloʊʒər/)项目那样,我们会得到一个空白的变更日志、一个用于建立文档的目录、一个Eclipse公共许可证副本、一个project.clj文件(该文件告诉leiningen如何构建和运行我们的代码)以及一个名为README的自述文件。resources目录是用于存放数据文件的地方,比如我们想进行测试的数据库的配置文件。src目录存放着源代码,并按照代码中命名空间的结构被组织成一系列目录和文件。test目录是用于存放测试代码的目录。值得一提的是,这整个目录就是一个“Jepsen测试”;test目录是沿袭大多数Clojure库的习惯生成,而在本文中,我们不会用到它。
我们将从编辑一个指定项目的依赖项和其他元数据的project.clj文件来开始。我们将增加一个:main命名空间,正如下面一段命令行所示。除了依赖于Clojure自身的语言库,我们还添加了Jepsen库和一个用于与etcd进行通信的Verschlimmbesserung库。
(defproject jepsen.etcdemo "0.1.0-SNAPSHOT"
:description "A Jepsen test for etcd"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:main jepsen.etcdemo
:dependencies [[org.clojure/clojure "1.10.0"]
[jepsen "0.2.1-SNAPSHOT"]
[verschlimmbesserung "0.1.3"]])让我们先尝试用lein run来运行这个程序。
运行完后看到这样的数据结果并不意外,因为我们尚未写任何实质性的代码让程序去运行。在jepsen.etcdemo命名空间下,我们需要一个main函数来接收命令行参数并运行测试。在src/jepsen/etcdemo.clj文件中我们定义如下main函数:
Clojure默认接收跟在lein run指令后的所有参数作为-main函数的调用参数。main函数接收长度可变的参数(即“&”符号),参数列表叫做args。在上述这段代码中,我们在“Hello World”之后打印参数列表。
Jepsen囊括了一些用于处理参数、运行测试、错误处理和日志记录等功能的脚手架。现在不妨引入jepsen.cli命名空间,简称为cli,然后将我们的main函数转为一个Jepsen测试运行器。
cli/single-test-cmd由jepsen.cli提供。它为测试解析命令行的参数并调用提供的:test-fn,然后应该返回一个包含Jepsen运行测试所需的所有信息的键值映射表(map)。在上面这个样例中,测试函数etcd-test从命令行中接受一些选项,然后用它们来填充一个什么都不处理的空测试(即noop-test)。
如上述代码块所示,没有参数的话,cli/run!会输出一个基本的帮助信息,提醒我们它接收一个命令作为其第一个参数。现在让我们尝试添加一下test命令吧!
如上面展示的代码块所示,我们发现Jepsen启动了一系列的workers(类似于进程)。每一个worker负责执行针对数据库的操作。此外,Jepsen还启动了一个nemesis,用于制造故障。由于它们尚未被分配任何任务,所以它们马上便关闭了。Jepsen将这个简易测试的结果输出写到了store目录下,并打印出一个简要分析。
noop-test默认使用名为n1、n2 ... n5的节点。如果你的节点有不一样的名称,该测试会因无法连接这些节点而失败。但是这并没关系。你可以在命令行中来指定这些节点名称:
亦或者通过传入一个文件名来达到相同目的。文件中要包含节点列表,且每行一个。如果你正在使用AWS Marketplace集群,一个名为nodes的文件已经生成于机器的home目录下,随时可用。
如果你当前依然在不断地遇到SSH错误,你应该检查下你的SSH是否代理正在运行并且已经加载了所有节点的密钥。ssh some-db-node应该可以不用密码就连接上数据库。你也可以在命令行上重写对应的用户名、密码和身份文件。详见lein run test --help。
在本指导教程中,我们将全程使用lein run test ...来重新运行我们的Jepsen测试。每当我们运行一次测试,Jepsen将在store/下创建一个新目录。你可以在store/latest中看到最新的一次运行结果。
history.txt展示了测试执行的操作。不过此处运行完的结果是空的,因为noop测试不会执行任何操作。jepsen.log文件拥有一份测试输出到控制台日志的拷贝。results.edn展示了对测试的简要分析,也就是每次运行结束我们所看到的输出结果。最后,test.fressian拥有测试的原始数据,包括完整的机器可读的历史和分析,如果有需要可以对其进行事后分析。
Jepsen还带有内置的Web浏览器,用于浏览这些结果。 让我们将其添加到我们的main函数中:
上述代码之所以可以发挥作用,是因为cli/run!将命令名称与命令处理器做了映射。我们将这些映射关系用merge来合并。
我们可以在网络浏览器中打开http://localhost:8080来探究我们的测试结果。当然,serve命令带有其自己的选项和帮助信息:
打开一个新的终端窗口,并在其中一直运行Web服务器。 那样我们可以看到测试结果,而无需反复启动和关闭服务器。
有了这个基础之后,我们将编写代码来设置和拆除数据库。
Last updated
Was this helpful?