手撸软件测试框架——lua版(四)

2023-11-01

  本文简单介绍一下开发测试用例用到的几个关键接口。

1. 断言

  在测试用例中少不了对结果进行校验,校验的方法一般称为断言(assert),也就是说,在进行一系列的操作之后,断定会出现某个确定性的结果,如果这个确定性的结果如期出现,则断言成功,被测试对象也就通过测试,否则就没通过测试。

  本框架中的断言接口如下:

-- result:一个可以返回bool值的表达式,true表示测试通过
-- desc:附加描述,一般是对测试没通过的描述 
function GBT_ASSERT(result, desc)
    if result then return end -- 测试通过,不需要做什么
	
	-- 下面几行代码主要是提取一些信息,以便给用户提供详细的结果信息,比如:
	-- 测试用例名、用例所在lua文件名及行号,附加描述等。
    local info = debug.getinfo(2, "Sl") -- 调用栈不包含本断言函数
    local i, j = string.find(info.short_src, "%s*%-%s*%[%d+%]")
    local script = info.short_src
    if i and i > 1 then
        script = string.sub(script, 1, i - 1)
    end
    
    -- 这里可以插入代码,将测试结果信息报告给用户界面
	
    -- 开发人员可能会在一个用例里面下多个断言,而第一个失败的断言应该终止本用例的执行,所以这里调用
    -- yield并以nil参数通知主线程,不用真正挂起该线程,而是直接释放掉该线程,继续执行后面的用例。
    -- 可参见前文中Test_Node:ExecuteCase函数的实现。
    coroutine.yield()
end

  该接口的使用方法很简单,比如在一个MMORPG游戏中,开发一个简单的商城购买宝石的用例,该用例首先将角色的银两清空,然后购买宝石,最后断言购买不成功:

function GB_BuyDiamond_Money_NoEnough()
    ClearMoney() -- 调用系统内部的函数,清空银两
    BuyDiamond() -- 一系列的购买操作
    local r = FindDiamondInPacket() -- 在包裹中查找购买到的宝石
    GBT_ASSERT(r ~= true, "银两不足居然能买到宝石?")
end

2. 挂起

  前文中有提到过,在某些情况下需要等待一段时间之后再进行其它操作或者校验,因此需要一个等待指定时间后恢复的接口:

-- 挂起用例,等待指定时间后恢复执行
-- ms:毫秒数
function GBT_WAIT(ms)
	-- 这里以等待的毫秒数调用yield,在主线程中coroutine.resume(TC_Context.co)返回
	-- 该毫秒数,然后以这个毫秒数启动定时器,在下一次迭代恢复本用例的执行,从而实现挂起
    coroutine.yield(ms)
end

  该接口的使用方法也很简单,仍以上文中的商城购买宝石为例,该用例首先将角色的银两数调整为一颗宝石的价格,然后购买宝石,最后断言购买成功,且银两数变为0:

function GB_BuyDiamond()
    SetMoney(100) -- 假设商城中一颗宝石的价格是100银两
    BuyDiamond() -- 一系列的购买操作
    GBT_WAIT(2000) -- 等待两秒钟
    local r = FindDiamondInPacket() -- 在包裹中查找购买到的宝石
    GBT_ASSERT(r == true, "银两足够为什么买不到宝石?")
    r = GetMoney()
    GBT_ASSERT(r == 0, "购买宝石后银两扣除不正确!")
end

3. 延时

  这个接口,先列出代码:

-- ms:毫秒数
function GBT_DELAY(ms)
    TC_Context:SetDelay(ms)
end

  仍以上文中的购买宝石为例:

function GB_BuyDiamond()
    SetMoney(100)
    BuyDiamond()
    GBT_WAIT(2000)
    local r = FindDiamondInPacket()
    GBT_ASSERT(r == true, "银两足够为什么买不到宝石?")
    r = GetMoney()
    GBT_ASSERT(r == 0, "购买宝石后银两扣除不正确!")
    GBT_DELAY(1000) -- 本用例执行完毕,1秒后继续执行后面的用例
end

  购买宝石测试通过,最后在离开该用例的时候设置了1秒延时,告诉框架,1秒之后再继续执行后面的用例。


  其实,该接口并非必需,你仍然可以用GBT_WAIT(1000)来代替。区别就是GBT_WAIT(1000)会挂起当前用例,1秒之后恢复该用例继续执行(但马上就执行完),而GBT_DELAY(1000)不会挂起用例,一般用在一个用例函数的最后一行。大家可能已经看出来了,也可以用这个接口来实现前面的购买宝石的挂起-恢复-校验的用例,只是需要将上文的用例一分为二(这两个用例需要一前一后顺序注册到框架中):

-- 用例1,仅做购买操作,不进行校验
function GB_BuyDiamond()
    SetMoney(100)
    BuyDiamond()
    GBT_DELAY(2000) -- 本用例执行完,等待两秒钟,继续执行后面的用例
end

-- 用例2,仅做校验操作
function GB_BuyDiamond_Check()
    local r = FindDiamondInPacket() -- 在包裹中查找购买到的宝石
    GBT_ASSERT(r == true, "银两足够为什么买不到宝石?")
    r = GetMoney()
    GBT_ASSERT(r == 0, "购买宝石后银两扣除不正确!")
end

  这种实现方法,因为没有挂起任何用例函数,所以不需要使用lua的协程,就能实现“挂起等待恢复”的机制(当然,本框架实际上使用了lua协程机制)。至于用哪一种方法实现“挂起等待恢复”机制,看个人喜好了。

4. 结语

  到目前为止,整个框架介绍的差不多了,你可以用本系列中介绍的方法手撸出一个简单的测试框架,并且可以开始撰写大量的测试用例了。


  本框架的核心代码不超过1000行;但是,测试框架本身的代码虽然能跑起来,但并不具备可用性!你还是需要在一个支持树形控件的UI框架上,开发出几个界面来:

  • 用例树界面(这里有样图)
  • 运行主界面(这里有样图)
  • 或许还需要右键菜单(如果是手游项目,不需要右键菜单)
  • 用例统计界面(不是必需),可以用于统计各部门各系统各开发人员开发了多少用例
  • 其它界面

  开发这些UI界面的代码量差不多在1000行以上了。本人开发过3个版本的UI界面,分别基于MFC、unity3D和CEGUI(CEGUI没有合用的树形控件,本人曾在CEGUI中手撸了一个树形控件),代码量都在1500左右。限于篇幅,且UI部分依赖于具体产品所使用的UI框架,就不展开讨论了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手撸软件测试框架——lua版(四) 的相关文章

  • Lua math.random 不起作用

    所以我正在尝试创建一些东西 并且我到处寻找生成随机数的方法 然而 无论我在哪里测试代码 它都会产生非随机数 这是我写的一个例子 local lowdrops Wooden Sword Wooden Bow Ion Thruster Mach
  • docker 单元测试设置

    我想为我的产品设置一个单元测试环境 我有一个基于 Lua 中的 nginx 构建的 Web 应用程序 它使用 mysql 和 redis 我认为 docker 会对此很有帮助 尽管我是 docker 的新手 我的应用程序运行在 centos
  • 如果模式匹配,则打印 lua 表中的值

    好吧 我最近刚接触 lua 发现自己陷入了以下困境 我有函数peripheral getNames 这是一个自定义函数 它将返回一个具有结构 key value 的表 而 key 始终是一个数字 从 1 开始 value 将是该函数找到的内
  • Lua 中的“加载”有什么作用?

    我试图解决我的理解问题loadLua 脚本中的函数 但没有该命令的任何示例或指南 它在他自己的 Lua 网站上讲述https www lua org manual 5 2 manual html pdf load https www lua
  • 设置私有 luarocks 存储库

    对于我的设置 我需要一个 luarocks rock 的私有存储库 我可以将它们安装在我的开发环境中 而无需连接到互联网 为 luarocks 设置远程存储库的步骤是什么 我可以使用 sftp 服务器吗 有人有过这样的经历吗 在深入研究这个
  • Lua中如何去除字符串中的空格?

    我想从 Lua 中的字符串中删除所有空格 这是我尝试过的 string gsub str string gsub str string gsub str s 这似乎不起作用 如何删除所有空格 它有效 您只需分配实际结果 返回值 使用以下变体
  • 迭代包括空行在内的行

    给定一个带有一些空行的多行字符串 我如何在Lua中迭代行包括空行 local s foo nbar n njim for line in magiclines s do print line and blank or line end gt
  • 如何使用循环将字符串连接成一个?

    有人可以帮我解决字符串连接问题吗 我从寄存器读取数据 它的函数 utf regAddr length 我得到带有十进制数字的表格 然后将其转换为十六进制并循环字符串 我需要将这些字符串连接成一个 Lua中没有像 这样的操作符 functio
  • 使用 EVAL、SCAN 和 DEL 的 Redis 通配符删除脚本返回“非确定性命令后不允许写入命令”

    因此 我正在寻求构建一个 lua 脚本 该脚本使用 SCAN 根据模式查找键并删除它们 原子地 我首先准备了以下脚本 local keys local done false local cursor 0 repeat local resul
  • Lua:冒号符号、“自我”和函数定义与调用

    我对定义 调用 Lua 函数时使用的冒号表示法感到非常困惑 我以为我已经明白了 直到我看到这段代码 function string PatternSafe str return str gsub pattern escape replace
  • 什么更快?循环或多个 if 条件

    我想知道什么更快 是只用一条指令 即 1 1 执行 9 次 for 循环还是执行 9 个 if 条件时 我认为 if 更快 因为您不需要检查循环中的指令 它应该几乎相同 因为for循环本质上是检查if条件为真并运行一段代码 非常类似于if声
  • Lua 中的内联条件(a == b ? "yes" : "no")?

    无论如何 Lua 中可以使用内联条件吗 Such as print blah a true blah nahblah Sure print blah a and blah or nahblah
  • 如何在aerospike中获取ttl为-1的记录集?

    我在aerospike中有很多记录 我想获取ttl为 1的记录 请提供解决方案 只是为了澄清 设置TTL 为 1 https github com aerospike aerospike client go blob master docs
  • 尝试将 nil 与数字堆栈回溯进行比较?

    我正在通过以下链接玩 Lua https www lua org pil 4 2 html https www lua org pil 4 2 html并对某一点感到困惑 Lua 5 2 4 Copyright C 1994 2015 Lu
  • Lua中如何获取表中的最大整数?

    Lua中如何获取表中的最大整数 在Lua 5 1及更早版本中 你可以使用 math max unpack 1 2 3 4 5 这受到Lua堆栈大小的限制 在 PUC Lua 5 1 上 该值的最大值可达 ca 8000 个数字 如果堆栈空闲
  • 为什么 LuaJIT 这么好?

    编辑 不幸的是 LuaJIT 已从下面链接的比较中删除 This 比较 http shootout alioth debian org u64 which programming languages are fastest php编程语言的
  • 在lua中组合两个函数

    我刚开始学习lua 所以我的要求可能是不可能的 现在 我有一个接受函数的方法 function adjust focused window fn local win window focusedwindow local winframe w
  • 使用 FastCGI 运行 Lua 脚本

    我目前正在尝试找出使用 FastCGI 与 lighttpd 或 Nginx 一起运行 Lua 脚本的方法 我唯一能挖到的是WSAPI http keplerproject github com wsapi 开普勒计划的一部分 但我想知道是
  • Lua中按字符分割字符串

    我有像这样的字符串 ABC DEF 我需要将它们分开 字符并将两个部分分别分配给一个变量 在 Ruby 中 我会这样做 a b ABC DEF split 显然Lua没有这么简单的方法 经过一番挖掘后 我找不到一种简短的方法来实现我所追求的
  • 检查多个位置的值并仅在源唯一时返回匹配项

    假设我有一个清单Vendors 阿斯达 乐购 Spar 我有一个清单Sources 或者这个类比中的供应商 家乐氏 Kellogg 吉百利 Cadbury 雀巢 Nestle 强生 Johnsons 帮宝适 Pampers Simple 等

随机推荐

  • window服务器上发布net项目,在windows服务器上使用winsw部署spring boot项目

    简介 springboot项目需要在windows上部署 spring官方推荐使用winsw来将springboot项目作为服务运行 参考 安装使用 winsw的使用比较简单 从github上下载 winsw下载 要下载的文件有两个 1 w
  • 《Kotlin从小白到大牛》第22章:Kotlin I/O与文件管理

    第22章 Kotlin I O与文件管理 Kotlin I O 输入与输出 是基于Java I O流技术 但是Java I O流技术使用起来比较繁琐 Kotlin提供了很多扩展 使代码变得简洁 本章介绍Kotlin I O流和文件管理相关知
  • 使用jstack排查线上故障:高CPU占用

    1 前言 一个应用占用CPU很高 除了确实是计算密集型应用之外 通常原因都是出现了死循环 我们以当时出现的实际故障为例 来介绍怎么定位和解决这类问题 2 排查步骤 思路 找出tomcat 进程中使用CPU最高 时间最长的线程 分析堆栈信息
  • Java中栈的实现(1)-使用顺序存储结构(数组)以及实现

    栈和队列其实是与普通的线性发展而来的 为普通的线性表增加一些特殊的限制就可以得到栈和队列了 从功能上看 栈和队列比普通的线性表功能相对弱一点 但是在特殊的场合下 使用栈和队列更有利 例如 编译器在实现函数的调用的时候需要使用栈来存储断点 实
  • js中apply方法的使用详细解析_宿雪家的小镇_新浪博客

    1 对象的继承 一般的做法是复制 Object extendprototype js的实现方式是 复制代码代码如下 Object extend function destination source for property in sour
  • Android平台实现ping功能方案----避过ping数据构建需要root权限的限制

    PingForAndroid C库采用SOCK DGRAM方式构建icmp包 避开raw socket必须root权限的限制 实现ping功能 Github https github com bgylde PingForAndroid pi
  • linux shell 等待输入_shell中获得用户的输入

    有时我们需要shell脚本有更多的交互性 比如我们安装某个linux命令的时候 会提示 N Y 选择安装或者放弃 这时就需要用到shell的read命令 read命令的基本使用 演示代码如下 其中 n表示字符串输出尾端不换行 还可以直接在r
  • R语言 回归诊断几种方法

    回归诊断技术提供了评价回归模型使用性的必要工具 能帮助发现并且纠正问题 有几种方法进行回归诊断 分别是标准方法 car包中的函数 gvlma函数 建议先通过gvlma函数进行验证 如果违反假设条件 再使用其他方法来判断哪些假设没有满足并进行
  • Cloud Run min实例:最小化无服务器的冷启动

    作者 Kelsey Hightower Vinod Ramachandran 无服务器最为优异的一点在于其按需付费的操作模型 可以让用户将服务规模缩减为零 但是对于某些应用程序来说 无服务器对于他们来说没那么重要的原因也在于其模型可以按需缩
  • 春秋云镜 CVE-2022-24112

    春秋云镜 CVE 2022 24112 Apache APISIX batch requests SSRF RCE 漏洞 靶标介绍 Apache Apisix是美国阿帕奇 Apache 基金会的一个云原生的微服务API网关服务 该软件基于O
  • opencv 轮廓放大_使用OpenCV和Python构建自己的车辆检测模型

    概述 你对智慧城市领域有兴趣吗 如果是的话 你会喜欢这个关于实现你自己的车辆检测系统的教程 在深入实现部分之前 我们将首先了解如何检测视频中的移动目标 我们将使用OpenCV和Python构建自动车辆检测器 介绍 关于智慧城市的理念 以及自
  • 三分钟了解腾讯云DDOS基础防护

    三分钟了解腾讯云DDOS基础防护 DDoS 基础防护应用场景包括哪些 腾讯云 DDoS 基础防护应用于攻击频率不高且攻击峰值不超过基础防护阈值的 DDoS 攻击防护场景 当攻击流量超过一定流量时 将自动启动 DDoS 清洗设备进行流量清洗
  • nettty

    https www jianshu com p e58674eb4c7a 1 Netty 异步和事件驱动 1 Netty 能够帮助搭建允许系统能够扩展到支持150000名并发用户 2 Netty 设计关键 异步 事件驱动 1 1 Java网
  • Linux下JDK1.8安装及配置

    进入Linux系统Ubuntu debian或centos安装JDK1 8并配置环境变量 通过终端在 opt目录下新建base文件夹 命令行 sudo mkdir opt base 然后进入java目录 命令行 cd opt base 到官
  • Ubuntu安装Nvidia显卡驱动

    原来没那么复杂 https linuxconfig org how to install the nvidia drivers on ubuntu 18 04 bionic beaver linux 我用的第一种方法 安装途中遇到了一个 v
  • php ajax右边悬浮购物车,一个简单的php+Ajax购物车程序代码(1/2)_PHP教程

    cart name name this gt items SESSION this gt cart name setItemQuantity Set the quantity of an item param string order co
  • 远程服务器docker配置并启动jupyter lab

    前提摘要 在远程服务器docker中存在镜像 但想通过jupyter lab来更好的可视化代码结果 首先登录远程服务器ssh 并拉取镜像 p是端口映射 22给ssh连接 jupyter lab的默认端口是8889 8888是自己的端口号 n
  • Ubuntu下OpenResty 搭建高性能服务端

    Socke 介绍 Linux Socket 编程领域为了处理大量连接请求场景 需要使用非阻塞 I O 和复用 select poll epoll 是 Linux API 提供的 I O 复用方式 自从 Linux2 6 中加入了 epoll
  • 函数式,F#都做了哪些优化?

    非函数式语言中使用函数式风格的缺点 函数式的优点 想必大家都已经非常了解了 我们来看看 一般语言使用函数式风格可能带来的问题 变量默认是可变的 为了实现不可变性 开发者只能人为的规范不去改变变量的值 没有明确的变量修改提示 容易因失误改变变
  • 手撸软件测试框架——lua版(四)

    本文简单介绍一下开发测试用例用到的几个关键接口 1 断言 在测试用例中少不了对结果进行校验 校验的方法一般称为断言 assert 也就是说 在进行一系列的操作之后 断定会出现某个确定性的结果 如果这个确定性的结果如期出现 则断言成功 被测试