|
|
|
|
@ -1,64 +1,124 @@
|
|
|
|
|
# 导入 JSON 模块:用于将 Python 字典序列化为 JSON 字符串(适配接口的 JSON 数据格式)
|
|
|
|
|
import json
|
|
|
|
|
|
|
|
|
|
# 导入 Django 测试核心工具:
|
|
|
|
|
# - Client:模拟客户端发起 HTTP 请求(GET/POST 等),用于测试视图接口
|
|
|
|
|
# - RequestFactory:生成原始请求对象(适用于单独测试视图函数/类,本用例未直接使用)
|
|
|
|
|
# - TestCase:Django 单元测试基类,提供断言方法、测试环境初始化/清理等功能
|
|
|
|
|
from django.test import Client, RequestFactory, TestCase
|
|
|
|
|
|
|
|
|
|
# 导入跨应用模型:BlogUser(用户模型,用于测试登录权限相关接口)
|
|
|
|
|
from accounts.models import BlogUser
|
|
|
|
|
# 导入当前应用的测试目标模型:OwnTrackLog(轨迹数据模型,用于验证数据读写)
|
|
|
|
|
from .models import OwnTrackLog
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Create your tests here.
|
|
|
|
|
# 说明:该注释为 Django 自动生成,提示开发者在此处定义测试类/测试方法
|
|
|
|
|
|
|
|
|
|
class OwnTrackLogTest(TestCase):
|
|
|
|
|
"""
|
|
|
|
|
轨迹数据相关接口与模型单元测试类:
|
|
|
|
|
继承自 TestCase,专注测试 OwnTrackLog 模型的数据读写及相关视图接口(/owntracks/ 下的接口)
|
|
|
|
|
测试覆盖场景:数据提交(合法/非法)、接口权限控制、响应状态码验证
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def setUp(self):
|
|
|
|
|
"""
|
|
|
|
|
测试前置初始化方法:
|
|
|
|
|
在每个测试方法执行前自动调用,用于创建测试所需的公共资源
|
|
|
|
|
作用:避免重复代码,确保每个测试方法的环境一致性
|
|
|
|
|
"""
|
|
|
|
|
# 初始化客户端对象:模拟浏览器发起 HTTP 请求,后续所有接口测试均通过该对象执行
|
|
|
|
|
self.client = Client()
|
|
|
|
|
# 初始化请求工厂对象:用于生成自定义请求(本用例未直接使用,预留扩展)
|
|
|
|
|
self.factory = RequestFactory()
|
|
|
|
|
|
|
|
|
|
def test_own_track_log(self):
|
|
|
|
|
"""
|
|
|
|
|
核心测试方法:命名以 test_ 开头(Django 测试框架自动识别执行)
|
|
|
|
|
测试内容:
|
|
|
|
|
1. 合法轨迹数据提交(完整字段)→ 验证数据是否成功写入数据库
|
|
|
|
|
2. 非法轨迹数据提交(缺少必填字段)→ 验证数据是否被拒绝(数据库无新增)
|
|
|
|
|
3. 未登录状态访问需权限接口 → 验证是否重定向(302)
|
|
|
|
|
4. 管理员登录后访问接口 → 验证是否正常响应(200)
|
|
|
|
|
5. 管理员登录后操作模型 → 验证数据写入及接口查询功能
|
|
|
|
|
"""
|
|
|
|
|
# --------------- 场景1:提交完整合法的轨迹数据(tid、lat、lon 字段齐全)---------------
|
|
|
|
|
# 构造合法的请求数据字典:包含模型所需的所有必填字段
|
|
|
|
|
o = {
|
|
|
|
|
'tid': 12,
|
|
|
|
|
'lat': 123.123,
|
|
|
|
|
'lon': 134.341
|
|
|
|
|
'tid': 12, # 用户标识(整数类型,模型中 CharField 会自动转换为字符串存储)
|
|
|
|
|
'lat': 123.123, # 纬度(合法浮点数)
|
|
|
|
|
'lon': 134.341 # 经度(合法浮点数)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 模拟 POST 请求:向轨迹提交接口发送 JSON 格式数据
|
|
|
|
|
self.client.post(
|
|
|
|
|
'/owntracks/logtracks',
|
|
|
|
|
json.dumps(o),
|
|
|
|
|
content_type='application/json')
|
|
|
|
|
length = len(OwnTrackLog.objects.all())
|
|
|
|
|
self.assertEqual(length, 1)
|
|
|
|
|
'/owntracks/logtracks', # 请求接口路径(需与 urls.py 中配置一致)
|
|
|
|
|
json.dumps(o), # 请求体:将字典序列化为 JSON 字符串
|
|
|
|
|
content_type='application/json' # 指定请求头:声明数据格式为 JSON
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# 验证:数据库中是否新增 1 条轨迹记录(断言实际数量与预期一致)
|
|
|
|
|
length = len(OwnTrackLog.objects.all()) # 查询所有轨迹记录的数量
|
|
|
|
|
self.assertEqual(length, 1) # 断言数量为 1 → 验证合法数据提交成功
|
|
|
|
|
|
|
|
|
|
# --------------- 场景2:提交非法轨迹数据(缺少必填字段 lon)---------------
|
|
|
|
|
# 构造非法请求数据:缺少经度(lon)字段(模型中 lon 为必填字段,无 null=True 配置)
|
|
|
|
|
o = {
|
|
|
|
|
'tid': 12,
|
|
|
|
|
'lat': 123.123
|
|
|
|
|
'tid': 12, # 用户标识
|
|
|
|
|
'lat': 123.123 # 纬度(仅含该字段,缺少 lon)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# 再次向同一接口发送非法数据
|
|
|
|
|
self.client.post(
|
|
|
|
|
'/owntracks/logtracks',
|
|
|
|
|
json.dumps(o),
|
|
|
|
|
content_type='application/json')
|
|
|
|
|
|
|
|
|
|
# 验证:数据库记录数量是否仍为 1(非法数据未被写入)
|
|
|
|
|
length = len(OwnTrackLog.objects.all())
|
|
|
|
|
self.assertEqual(length, 1)
|
|
|
|
|
self.assertEqual(length, 1) # 断言数量不变 → 验证非法数据被拒绝
|
|
|
|
|
|
|
|
|
|
# --------------- 场景3:未登录状态访问需权限的地图展示接口 ---------------
|
|
|
|
|
# 模拟 GET 请求:未登录状态下访问 /owntracks/show_maps 接口
|
|
|
|
|
rsp = self.client.get('/owntracks/show_maps')
|
|
|
|
|
self.assertEqual(rsp.status_code, 302)
|
|
|
|
|
|
|
|
|
|
# 验证:响应状态码是否为 302(重定向,通常跳转到登录页)
|
|
|
|
|
self.assertEqual(rsp.status_code, 302) # 断言重定向 → 验证接口权限控制生效
|
|
|
|
|
|
|
|
|
|
# --------------- 场景4:创建管理员用户并登录 ---------------
|
|
|
|
|
# 创建超级用户(管理员):用于测试登录后访问权限接口
|
|
|
|
|
user = BlogUser.objects.create_superuser(
|
|
|
|
|
email="liangliangyy1@gmail.com",
|
|
|
|
|
username="liangliangyy1",
|
|
|
|
|
password="liangliangyy1")
|
|
|
|
|
email="liangliangyy1@gmail.com", # 邮箱(超级用户必填字段)
|
|
|
|
|
username="liangliangyy1", # 用户名(登录账号)
|
|
|
|
|
password="liangliangyy1") # 密码(登录密码)
|
|
|
|
|
|
|
|
|
|
# 模拟管理员登录:使用上述创建的账号密码登录系统
|
|
|
|
|
self.client.login(username='liangliangyy1', password='liangliangyy1')
|
|
|
|
|
|
|
|
|
|
# 手动创建一条轨迹记录(用于后续接口查询测试)
|
|
|
|
|
s = OwnTrackLog()
|
|
|
|
|
s.tid = 12
|
|
|
|
|
s.lon = 123.234
|
|
|
|
|
s.lat = 34.234
|
|
|
|
|
s.save()
|
|
|
|
|
s.tid = 12 # 设置用户标识
|
|
|
|
|
s.lon = 123.234 # 设置经度
|
|
|
|
|
s.lat = 34.234 # 设置纬度
|
|
|
|
|
# creation_time 字段使用默认值(当前时间),无需手动赋值
|
|
|
|
|
s.save() # 保存到数据库
|
|
|
|
|
|
|
|
|
|
# --------------- 场景5:登录后访问各类接口,验证响应状态 ---------------
|
|
|
|
|
# 1. 访问日期列表接口 → 预期 200(正常响应)
|
|
|
|
|
rsp = self.client.get('/owntracks/show_dates')
|
|
|
|
|
self.assertEqual(rsp.status_code, 200)
|
|
|
|
|
|
|
|
|
|
# 2. 再次访问地图展示接口 → 预期 200(已登录,权限通过)
|
|
|
|
|
rsp = self.client.get('/owntracks/show_maps')
|
|
|
|
|
self.assertEqual(rsp.status_code, 200)
|
|
|
|
|
|
|
|
|
|
# 3. 访问轨迹数据查询接口(无日期参数)→ 预期 200
|
|
|
|
|
rsp = self.client.get('/owntracks/get_datas')
|
|
|
|
|
self.assertEqual(rsp.status_code, 200)
|
|
|
|
|
|
|
|
|
|
# 4. 访问轨迹数据查询接口(带日期参数)→ 预期 200
|
|
|
|
|
rsp = self.client.get('/owntracks/get_datas?date=2018-02-26')
|
|
|
|
|
self.assertEqual(rsp.status_code, 200)
|
|
|
|
|
# 注:此处仅验证接口是否正常响应(状态码 200),未验证返回数据的正确性,可根据需求补充数据断言
|