mojito
mojito是一个简单而灵活的测试框架,最初开发它是为了解决OpenSearch前端测试中遇到的一些问题,但是随着mojito的开发,我们发现它可以被应用在更广泛的范围里。
mojito目前只是测试工具,而非测试服务。用户可以按照其规则,通过yaml文件定义测试工程和测试用例,并使用mojito来执行这些用例。而mojito的一个强大之处在于,它可以很方便的进行扩展。在mojito看来,任何测试用例都是由一组“测试行为(action)”组成的,除了先天内置的一些action外,用户可以直接在yaml文件里自定义新的action,来基于已有action进行扩展或组合。后面会有详细介绍。
在自定义action的基础上,mojito还支持优美的上下文系统。用户可以分别在工程(project)、用例(case)、行为(action)这几个方面进行递进的变量定义和传递。
在公司内部,有一些和mojito类似的测试框架,例如tiramisu和ATest,mojito不是为了替代这些框架,而是纯粹为了更好的适应OpenSearch的测试。已有框架在扩展性和易用性上存在一些问题,使得OpenSearch开发自己的mojito的成本在某种意义上低 于应用那些框架。同时,mojito也是搜索测试对Clojure语言应用在测试开发中的一个尝试,不得不说,到目前为止,收效符合预期。
名称来源:mojito原意是一种鸡尾酒 (link),来源于古巴,是大作家海明威的最爱。话说起这个名字的由来也属偶然。mojito的开发过程参考了很多tiramisu的思想和“外观”,于是在起名字的时候,就也想找一个甜点蛋糕的名字来命名,结果没找到什么合适的。此时刚好想起了夏天最爱喝的一种酒精饮料:mojito。青柠的酸爽配上薄荷的清凉,白朗姆的甘冽沉浸在苏打水的泡泡中,简直是夏日的绝佳消暑饮品。帝都找不到正宗的mojito卖,于是每年夏天,老婆都会给我自制上几次,即使是冬天,那味道也常常在脑海中回荡。给这个工具起这个名字,也是希望我们的测试功能能够爽酷起来吧。
安装
请从此处下载mojito的最新版本
下载后解压,并把解压后的文件夹添加到可执行目录即可。
使用方法
注意:请在使用前确保jre1.7已经被正确安装,且java命令在当前path路径内
运行项目:
mojito run -p "project-path"
获取帮助:
mojito -h
使用概述
如前文所说,mojito的核心理念是:所有的用例都由一系列“行为”组成,在mojito里被称为action。而一个测试项目就是多个测试用例(case)的组合,case之间是对等且隔离的,它们可以共用一些全局项目配置,但是在执行阶段是相互独立的。从 项目 到 用例 再到 行为,mojito是通过上下文系统来使之串联起来。
了解mojito的用法,最好的方式是通过示例工程。每个发布包里都包含一个sample-project目录,里面的yaml文件都包含大量注释或示例以供参考。
目录结构
先来看一下mojito的项目目录结构。打开发布包里的sample-project目录,你会看到如下的结构:
SAMPLE-PROJECT
│ project.yml
│
├─actions
│ call-openapi.yml
│ create-index.yml
│ delete-index.yml
│
├─cases
│ case1.yml
│ case2.yml
│ mysql-case.yml
│
├─data
│ mysql.csv
│ test_main.txt
│
├─mail
│ report.html
│
└─templates
各个目录(文件)的含义如下:
- project.yml文件(必选):项目的核心定义文件,定义了项目的全局信息(如 项目名称、项目描述等)和配置(如 并行数),也定义了顶层的环境变量(参考 上下文系统)
- cases目录(必选):所有的用例定义都必须在此目录下,可以有多层的目录
- actions目录(可选):存放用户的自定义action。在 自定义action 一节会有更详细的描述
- data目录(可选):存放用户用例中使用到的数据文件。其实mojito并没有规定用户数据文件放到哪儿,只是鼓励用户按照此规则存放
- mail目录(可选):用于存放用户的邮件模板。(此目录名只是约定,用户可以选用任何目录名)
- templates目录(保留):未来的mojito还会支持用例模板的功能,所以此目录保留给该功能使用,目前用户只需保留其为空即可
注意:所有mojito文件必须使用“UTF-8无BOM编码”,否则会出现乱码或其他未知错误
Hello Mojito
既然是程序员,第一个程序一定是Hello World。不过此处我们是 Hello Mojito。按照如下步骤,来创建我们的第一个测试项目,开启mojito之旅吧!
- 首先,我们创建一个测试项目的根目录,此处我们放在 d:\hello-mojito 下面
-
在该目录下创建一个文本文件,project.yml,其内容如下(注意:使用“UTF-8无BOM编码”):
name: hello-mojito desc: this is a HelloWorld project for mojito envs: - name: default desc: default environment config set-vars: strings: string1: Hello string2: Mojito
-
在该目录下创建一个新目录,命名为 cases
-
在cases目录下创建一个文本文件,hello-mojito.yml,其内容如下:
id: 1 title: Hello Mojito desc: Mojito上的第一个Hello World用例 envs: [default] set-vars: k: ${strings.string1}$ ${strings.string2}$ site: http://m.sm.cn steps: - action: http-action invoke-params: method: GET url: ${site}$/s headers: User-Agent: "Mozilla/5.0 (Windows NT 6.1; WOW64)" params: q: ${fn:urlescape(k)}$ by: submit from: smor ensure: equals: status: 200
-
然后执行指令
mojito run -p "d:\hello-mojito"
如果一切顺利,你会得到如下的输出:
2015-04-28 18:10:04 - [INFO] start executing project [hello-mojito]
2015-04-28 18:10:04 - [INFO] project params: verbose=0, env=default, tags=[], priority=[3], caselist=[], send-email=[true]
2015-04-28 18:10:04 - [INFO] thread 0 get a case [hello.yml], start to run
2015-04-28 18:10:04 - [INFO] start executing of case [hello.yml], title: Hello Mojito
2015-04-28 18:10:04 - [INFO] enter case startup
2015-04-28 18:10:04 - [INFO] leave case startup, result: success
2015-04-28 18:10:04 - [INFO] enter case steps: null
2015-04-28 18:10:04 - [INFO] start executing of action [http-action]
2015-04-28 18:10:05 - [INFO] action [http-action] successed
2015-04-28 18:10:05 - [INFO] end executing of action [http-action]
2015-04-28 18:10:05 - [INFO] leave case steps, result: success
2015-04-28 18:10:05 - [INFO] enter case teardown
2015-04-28 18:10:05 - [INFO] leave case teardown, result: success
2015-04-28 18:10:05 - [INFO] case [hello.yml] final result: PASS
2015-04-28 18:10:05 - [INFO] end executing of case [hello.yml]
2015-04-28 18:10:05 - [INFO] thread 0 finish case [hello.yml] running
2015-04-28 18:10:05 - [INFO] ================================================================================
2015-04-28 18:10:05 - [INFO] Project [hello-mojito] results
2015-04-28 18:10:05 - [INFO] ================================================================================
2015-04-28 18:10:05 - [INFO] Summaries:
2015-04-28 18:10:05 - [INFO] Start: 2015-04-28T10:10:04.754Z End: 2015-04-28T10:10:05.062Z
2015-04-28 18:10:05 - [INFO] Total: 1 Pass: 1 Fail: 0 Skip: 0 Timeout: 0
2015-04-28 18:10:05 - [INFO] Pass Rate: 100.00% Pure Pass Rate: 100.00%
2015-04-28 18:10:05 - [INFO] --------------------------------------------------------------------------------
2015-04-28 18:10:05 - [INFO] Case deatils:
2015-04-28 18:10:05 - [INFO] 2015-04-28T10:10:05.061Z PASS hello.yml
2015-04-28 18:10:05 - [INFO] ================================================================================
一切都很简单自然。我们一共执行了1个case,执行结果是PASS。其中该case(hello.yml)共有3个阶段,分别为startup、steps和teardown。我们在case的定义文件中,只定义了steps,没有定义startup和teardown,所以那两个步骤没有任何action需要执行。在steps阶段,只有一个action,就是http-action。如果在执行的时候使用-v参数,可以得到更详细的log,能够看到action的输入和输出。
再稍微多解释一下case的定义。在hello.yml的steps下面是一个列表,列出了需要执行的每个action,这些action会被顺次执行。此例中我们只有一个http-action调用。在action调用里面,我们传入了两组关键参数,其一是invoke-params,另一个是ensure。
- invoke-params:其内容为一个map,包含了action执行所需的参数。参数可以是任何类型(string、number、list、map),但其解释权归action所有。此例中的http-action,我们传了4个关键参数,用于调用神马搜索。
- ensure:定义了对action执行结果的验证,其值为一个map,其中map的key为验证类型。目前mojito只支持3种基本验证类型(equals、matches、exists),未来会支持更多的验证类型,以及验证的逻辑关系(and、or、not)。mojito认为,任何action的执行,其返回值都是一个map、list的组合。可以通过特定的语法来访问action的返回值,从而进行验证。例如在此例中,我们验证返回值的“status”字段(http-action的返回值是一个map)必须等于200,否则就会报错。更多关于ensure的内容参加下文 “action执行结果检验(ensure)”
定义project
在前文已经看到,每个测试工程都会有一个project.yml文件,用于定义工程整体的一些设置。其格式如下:
---
name