[python3] TestCase Description - Domain Specific Language Demo

DSL 是什么?

DSL的概念:以极其高效的方式描述特定领域的对象、规则和运行方式的语言

   DSL 其实是 Domain Specific Language 的缩写,中文翻译为领域特定语言(下简称 DSL);而与 DSL 相对的就是 GPL,这里的 GPL 并不是我们知道的开源许可证,而是 General Purpose Language 的简称,即通用编程语言,也就是我们非常熟悉的 Objective-C、Java、Python 以及 C 语言等等。

Wikipedia 对于 DSL 的定义还是比较简单的:

A specialized computer language designed for a specific task.
为了解决某一类任务而专门设计的计算机语言。

   与 GPL 相对,DSL 与传统意义上的通用编程语言 C、Python 以及 Haskell 完全不同。通用的计算机编程语言是可以用来编写任意计算机程序的,并且能表达任何的可被计算的逻辑,同时也是 图灵完备 的。

   但是在里所说的 DSL 并不是图灵完备的,它们的表达能力有限,只是在特定领域解决特定任务的。

A computer programming language of limited expressiveness focused on a particular domain.

   另一个世界级软件开发大师 Martin Fowler 对于领域特定语言的定义在笔者看来就更加具体了,DSL 通过在表达能力上做的妥协换取在某一领域内的高效

   而有限的表达能力就成为了 GPL 和 DSL 之间的一条界限。

常见 DSL :

  • Regex:正则表达式仅仅指定了字符串的 pattern,其引擎就会根据 pattern 判断当前字符串跟正则表达式是否匹配。
  • SQL:SQL 语句在使用时也并没有真正的执行,我们输入的 SQL 语句最终还要交给数据库来进行处理,数据库会从 SQL 语句中读取有用的信息,然后从数据库中返回使用者期望的结果。
  • HTML & CSS:HTML 和 CSS 只是对 Web 界面的结构语义和样式进行描述,虽然它们在构建网站时非常重要,但是它们并非是一种编程语言,正相反,我们可以认为 HTML 和 CSS 是在 Web 中的领域特定语言。

TC - DSL 是什么?

   TC - DSL(TestCase Description),测试案例描述语言,用于描述测试案例的测试步骤。

   有这个想法是因为我发现很多测试项有大量的重复垃圾代码,打印 log 混乱,并且没有办法轻松看出一个测试项是在测试什么,测试步骤是什么,什么时间点发生了什么,无法快速组合出新的测试项等等很多问题。

   为了解决这个问题,我首先是想到了使用 json, html 等语言来实现可配置,可是这些语言从一定程度上我感觉很繁琐,描述效果也不是很好,和我想要描述的效果有一定的差距,所以自己想出了一种语法,可以较好的描述测试项,报告测试步骤。

一、TC 语法

语法高亮使用 vscode 制作插件实现,文件后缀为 .tc
TC 语法

Key Word

  • auto:包含一系列 TestStep,后需要使用 {}() 描述有哪些测试步骤
  • import:导入其他 .tc 作为一个 TestStep

TestStep

  • 由 Key Word 一系列 TestStep 组成的也称为一个 TestStep
  • 图片中 green word 部分是单独 TestStep

Execution order

   只有 auto 后可以使用 {}() 修饰。

  • {}:代表顺序执行,执行完一个 TestStep 后执行下一个 TestStep
  • ():代表并行执行,TestStep 同时执行,所有 TestStep 运行完毕后结束,或是 TestStep fail 提前结束

Parameters

   参数使用 [] 表示,每一个参数用键值对表示,一般形式为 key=valval 有如下形式:

  • num:可以是 intfloat,如 50.15
  • bool:可以是 true True false False,其中 true 可省略,如图中 random 没有 = 默认为 true
  • string:字符串使用 "" 表示,转义字符只有 \"

TestStep 有一些共有的参数:

  • timeout:TestStep 需要在该时间内返回,否则认为超时,判断为 fail
  • loop:循环测试次数,将该 TestStep 测试 $(loop)
  • duration:该参数只作用于 auto () 和其他实现该参数的 TestStep,durationtimeoutauto () 上的行为和其他 TestStep 有一些区别,如果 auto () 内层 TestStep 有定义该参数则使用内层 TestStep 的 duration ,否则 auto () 会将 duration 参数传递到内层 TestStep,

Comment

  • /* */:多行注释
  • //:单行注释

二、TC 实现

1. lexical & syntax analysis

   因为 TC 的语法很简单,词法分析和语法分析也比较简单,毕竟不是真正的编程语言,做起来没有什么难度。

2. TestStep

   从前面可以看出,TestStep 大概分为三类:

  • 单独的 TestStep
  • 顺序执行的 TestStep
  • 并行执行的 TestStep (多进程,据说 python 多线程不是真正的并发)

所以抽象为几个类:

class TestStep:
	pass	# 单独的 TestStep, 抽象类,不应该直接实例化,实现一个具体的 TestStep 时继承它

class __TestStepList(TestStep):
	pass	# 中间层抽象类,不直接实例化,管理 “一系列 TestStep”

class TestStepSeq(__TestStepList):
	pass	# 顺序执行 TestStep

class TestStepSync(__TestStepList):
	pass	# 并行执行 TestStep

三、TC 使用

项目文件结构:

AutoTest                         # 顶级目录
├── auto.py                      # 由 'auto.py' 执行 .tc
├── only_for_test
│   ├── client.py
│   └── server.py
├── README.md
├── testCase
│   └── test.tc
└── TestStep                     # 存放 TestStep
    ├── core                     # 核心内容,语法分析、TestStep 基类等
    │   ├── .......
    │   └── base_TestStep.py
    ├── .......
    └── ts_hello.py              # 普通的 TestStep

Usage:
  python3 auto.py <xxx.tc> [show]

使用方法:

  • python3 auto.py xxx.tc:开始执行 xxx.tc 所描述的测试项
  • python3 auto.py xxx.tc show:查看 xxx.tc 测试项的测试内容

   需要添加新的 TestStep 时,继承 class TestStep,然后使用基类提供的一些 API,最后将新类命名为文件名(即:ts_hello.py 中定义 class ts_hello(TestStep)),并且放入 TestStep 文件夹即可,会自动搜索这些测试步骤。

例子:
以前面语法介绍的 .tc 为例:python3 auto.py testCase/test.tc show

xhr@ubuntu:~/study/python/AutoTest$ python3 auto.py testCase/test.tc show
==================================================
[1] import :<class 'ts_test_sync.ts_test_sync'>
[2] import :<class 'ts_send_data.ts_send_data'>
[3] import :<class 'ts_ping.ts_ping'>
[4] import :<class 'ts_hello.ts_hello'>
[5] import :<class 'ts_shell.ts_shell'>
[6] import :<class 'ts_fail.ts_fail'>
[7] import :<class 'ts_connect.ts_connect'>
[8] import :<class 'ts_goodbye.ts_goodbye'>
[9] import :<class 'ts_sleep.ts_sleep'>
[10] import :<class 'ts_test_seq.ts_test_seq'>
==================================================

--------------------------------------------------

 TestStep [TestStepSeq] None: {'timeout': 60, 'loop': 2}
   TestStep-1 [ts_shell] shell "echo 'start test'": {'cmd': "echo 'start test'"}
   TestStep-2 [ts_connect] connect to a server, client=host_default_client_random__: {'timeout': 1.5}
   TestStep-3 [TestStepSync] [Concurrent] : {'duration': 3}
     TestStep-3-1 [ts_ping] ping a PC: {'timeout': 7, 'loop': 2, 'duration': 5}
     TestStep-3-2 [ts_hello] Print "hello" repeatedly: {'timeout': 50, 'duration': 3}
     TestStep-3-3 [ts_hello] Print "hello" repeatedly: {'timeout': 50, 'duration': 3}
     TestStep-3-4 [ts_ping] ping a PC: {'timeout': 50, 'duration': 3}
   TestStep-4 [ts_send_data] send data to server, client=host_default_client_random__: {'timeout': 1.5}
   TestStep-5 [TestStepSync] [Concurrent] : {'duration': 5}
     TestStep-5-1 [ts_hello] Print "hello" repeatedly: {'random': True, 'duration': 5}
     TestStep-5-2 [ts_ping] ping a PC: {'random': False, 'duration': 5}
   TestStep-6 [ts_goodbye] Print once "goodbye": {'loop': 3}

--------------------------------------------------

这个简单的 Demo 还是运行得还不错,蛮有意思的,还有很多方面仍然有优化的余地。

源码

Github 实在是太慢了。。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值