RapidSMS 测试完整指南:脚本化测试与测试工具链从零实战
RapidSMS 测试完整指南:脚本化测试与测试工具链从零实战
【免费下载链接】rapidsms Build SMS applications with Python 项目地址: https://gitcode.com/gh_mirrors/ra/rapidsms
RapidSMS 是一个用 Python 构建短信应用的开源框架,而 RapidSMS 测试 则是保证消息路由、应用处理逻辑稳定可靠的关键一环。本文面向新手,完整介绍 RapidSMS 的脚本化测试(Scripted Testing)与内置测试工具链(Test Harness),从环境准备、编写第一个测试用例到运行整个测试套件,带你从零实战、快速上手。
如上图所示,SMS 消息从 GSM Modem、Kannel、HTTP 等后端进入,经过消息队列与 Router 的 Filter → Parse → Handle → Default → Cleanup 五个阶段,最终交给 Django 应用处理。RapidSMS 测试正是围绕这条完整链路展开的。
为什么要给 RapidSMS 应用写自动化测试
短信应用一旦上线,消息解析、多应用协作、数据库状态等问题都可能悄悄出现。自动化测试能反复验证你的代码是否按预期工作,确保新增功能不会破坏已有逻辑。官方文档 docs/topics/testing.rst 建议为所有 RapidSMS 应用编写测试,重点覆盖三个方面:
- 消息解析:应用如何区分
q和q ocean blue?会不会被多余空格或相似单词干扰? - 工作流:当数据库中没有题目、没有联系人时,应用会如何响应?
- 业务逻辑:答案判断、关键词匹配是否正确?
测试前的准备工作:环境与依赖
RapidSMS 测试基于标准的 Python unittest 与 Django 测试体系,你不需要额外学习新的测试框架。准备步骤如下:
- 克隆项目:
git clone https://gitcode.com/gh_mirrors/ra/rapidsms - 安装开发依赖,参考 tests/requirements/dev.txt
- 配置 Django settings 与测试数据库(项目内置 tests/default.py 和 tests/urls.py 可直接参考)
RapidSMS 测试工具链全景:五大核心组件
RapidSMS 在 rapidsms/tests/harness/ 下提供了一套开箱即用的测试工具链,核心组件包括:
| 组件 | 作用 |
|---|---|
RapidTest / RapidTransactionTest |
通用测试基类,自动装配 TestRouter,可检查收发消息 |
TestScript / TestScriptMixin |
脚本化测试框架,用对话式脚本编写集成测试 |
TestRouter |
记录所有入站/出站消息的路由器,供测试断言 |
CreateDataMixin / LoginMixin |
快速创建联系人、连接、消息等测试数据的辅助工具 |
MockBackend / EchoApp |
模拟后端与应用,隔离真实短信通道 |
其中 RapidTest、TestScript 等类在 rapidsms/tests/harness/init.py 中定义,TestRouter 在 rapidsms/router/test/router.py 中实现。
使用 RapidTest 编写第一个测试用例
RapidTest 提供了最简单的测试环境:通过 receive 模拟收到短信,通过 outbound 属性检查应用回复的内容。以官方文档中的问答应用为例:
from rapidsms.tests.harness import RapidTest
class QuizMeStackTest(RapidTest):
def test_no_questions(self):
"""数据库为空时,应回复提示信息"""
self.receive('q', self.lookup_connections('1112223333')[0])
self.assertEqual(self.outbound[0].text, 'No questions exist.')
短短几行代码,就完成了「短信进入 → 经过整个路由栈 → 应用响应」的全流程验证。lookup_connections 会自动创建 Connection 对象,无需手动准备数据。
检查数据库状态:更细粒度的断言
如果你的应用会写入数据库,可以用 RapidTest 结合 ORM 断言,检查测试后的数据状态:
msg = self.receive('q ocean blue', self.lookup_connections('1112223333')[0])
self.assertEqual(self.outbound[0].text, 'Correct!')
answer = Answer.objects.all()[0]
self.assertTrue(answer.correct)
self.assertEqual(msg.connection, answer.connection)
脚本化测试入门:像写剧本一样写测试
RapidSMS 的脚本化测试(Scripted Testing)是官方推荐的高层集成测试方式:把「用户发什么、系统回什么」写成一段对话脚本,交给框架自动执行和断言。脚本语法非常简单:
号码 > 短信内容:表示该号码发来一条入站消息号码 < 短信内容:表示系统向该号码回复一条出站消息
例如问答应用的完整对话可以写成:
1112223333 > q
1112223333 < What color is the ocean? Answer with 'q ocean <answer>'
1112223333 > q ocean blue
1112223333 < Correct!
在测试类中通过 runScript 执行这段脚本即可:
from rapidsms.tests.harness import TestScript
from quizme.app import QuizMeApp
class QuizMeScriptTest(TestScript):
apps = (QuizMeApp,)
def test_correct_script(self):
self.runScript("""
1112223333 > q
1112223333 < What color is the ocean? Answer with 'q ocean <answer>'
1112223333 > q ocean blue
1112223333 < Correct!
""")
注意 apps 必须在类级别定义,它告诉测试框架路由器要加载哪些应用。脚本解析与执行的完整逻辑位于 rapidsms/tests/harness/scripted.py,其中 parseScript 负责解析脚本,runParsedScript 负责按顺序执行并逐条比对消息。
脚本化测试进阶:日期、注释与顺序匹配
parseScript 还支持两个实用特性:
- 注释行:以
#开头的行会被忽略,方便为脚本添加说明 - 时间戳:在号码后附加
@年月日时分(如19232922@200804150730),可模拟指定时间到达的消息
脚本执行时按顺序处理:遇到 > 就发送入站消息,遇到 < 就从出站消息中查找匹配的回复。如果一条入站消息触发了多条回复,框架会逐一比对,直到找到匹配项——这保证了对话顺序的严谨性。
测试应用逻辑:脱离路由的快速单元测试
对于不依赖消息路由的纯业务逻辑,可以跳过整套路由架构,直接构造应用对象进行测试,执行速度更快:
from django.test import TestCase
from rapidsms.router.test import TestRouter
from quizme.app import QuizMeApp
class QuizMeLogicTest(TestCase):
def setUp(self):
self.app = QuizMeApp(TestRouter())
def test_inquiry_whitespace(self):
self.assertTrue(self.app.is_quiz(" q "))
如果只关心「消息是否到达路由器」,而不关心应用处理逻辑,还可以给 TestRouter 传入 disable_phases=True 跳过路由阶段,见 rapidsms/tests/harness/router.py。
常用测试辅助工具速查
- CreateDataMixin:提供
create_contact()、create_connection()、create_incoming_message()、random_string()等方法,一键生成测试数据,源码见 rapidsms/tests/harness/base.py - CustomRouterMixin:通过类属性
router_class和backends覆盖路由器与后端配置,用于测试自定义路由 - DatabaseBackendMixin:使用真实的 DatabaseBackend,并通过
sent_messages检查已发送消息 - MockBackend:把发送的消息存进内存列表,
clear()可清空收件箱,见 rapidsms/tests/harness/backend.py - LoginMixin:自动创建用户并登录,方便测试需要鉴权的 Web 视图
运行测试:run_tests.py 与 Django Test Runner
项目根目录的 run_tests.py 封装了 Django 测试运行器,用法如下:
python run_tests.py rapidsms # 运行整个框架的测试
python run_tests.py rapidsms.tests.test_scripted # 运行指定测试模块
python run_tests.py -v 2 --noinput # 详细输出、跳过交互提示
也可以直接用 Django 的方式运行:
python -m django test rapidsms --settings=tests.default
框架自带大量可直接借鉴的测试用例,例如 rapidsms/tests/test_scripted.py、rapidsms/tests/test_app_base.py、rapidsms/backends/test_base.py 以及 contrib 各应用的 tests 目录(如 rapidsms/contrib/messagelog/tests/)。
扩展:测试 Celery 异步任务与定时任务
如果项目使用 Celery 路由器(见 rapidsms/router/celery/),消息处理会异步化。这类场景下,除了断言消息本身,还要关注定时任务的配置与执行结果:
如上图所示,周期任务在 Django 管理后台中配置(名称、启用开关、Interval/Crontab 调度策略)。测试时应验证任务已正确注册、调度参数符合预期,并结合 Celery 的测试工具(如 celery.contrib.testing)模拟任务执行。
测试最佳实践与常见陷阱
- 从最小单元开始:先测试纯函数(如
check_answer),再逐层往上,失败时更容易定位问题 - 优先使用脚本化测试做集成验证:跨多个应用的消息流转用
TestScript最直观,但需要检查脚本中途的数据库状态时,改用RapidTest更灵活 - 保持收件箱干净:
TestScript.runScript会自动清空出站消息;手动测试时可用clear_sent_messages()清理 - 警惕旧 API:老版本
rapidsms/tests/scripted.py中的startRouter/stopRouter已标记为弃用,请使用新的rapidsms.tests.harness接口
结语
RapidSMS 测试并不神秘:RapidTest 帮你快速验证单条消息的处理,TestScript 让你用对话剧本完成端到端集成测试,再配合 CreateDataMixin、MockBackend 等工具,一套完整的测试体系很快就能搭建起来。希望这份 RapidSMS 测试完整指南能帮你写出稳定、可维护的短信应用,让每一次发布都更有底气。
【免费下载链接】rapidsms Build SMS applications with Python 项目地址: https://gitcode.com/gh_mirrors/ra/rapidsms
更多推荐


所有评论(0)