python自动化测试三部曲之request+django实现接口测试
Posted bai_nian_min_guo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python自动化测试三部曲之request+django实现接口测试相关的知识,希望对你有一定的参考价值。
国庆期间准备写三篇博客,介绍和总结下接口测试,由于国庆期间带娃,没有按照计划完成,今天才完成第二篇,惭愧惭愧。
这里我第一篇博客的地址:https://www.cnblogs.com/bainianminguo/p/11616526.html,主要是介绍unittest框架,有兴趣的同学们可以移步去查阅
这里废话少说,进入正题
我的思路是这样的
1、先用django实现登陆、增加、删除、查看4个接口
2、在excel定义好测试案例、然后读取excel中的案例,然后把案例用unittest框架组装和封装
3、启动django,执行测试案例
一、先跑通unittest到django的流程
1、先创建一个Django的项目
2、创建路由,这里我们使用二级路由
a、先复制工程目录下的urls.py文件到app目录下
b、修改工程目录下的urls.py文件,定义一级路由
c、修改app目录下的urls.py文件,设置二级路由,这里切记务必要删除默认的admin这条路由
d、定义这条路由指向的视图的函数
e、启动django,这里我们使用9090端口启动,因为我们的Jenkins端口用的是8080
E:\\python\\unittestForDjango>python manage.py runserver 9090
f、这里的是启动成功的样式,我圈住的告警可以忽略,因为这里Django的admin需要的,我们这里不会用到django的admin
g、打开浏览器访问django,我们的一个简单的Django项目已经跑通
3、在视图函数中定义一个方法,这个方法分别处理GET请求和POST请求
a、定义视图函数
这里通过这个参数告诉浏览器,我们返回的是JSON数据
return HttpResponse(result, content_type="application/json;charset=utf-8")
def test_login(request): method = request.method.upper() if method == "GET": result = {} name = request.GET.get("username",None) pwd = request.GET.get("pwd",None) result["name"] = name result["pwd"] = pwd result = json.dumps(result) # return HttpResponse(result) return HttpResponse(result, content_type="application/json;charset=utf-8") else: result = {} name = request.POST.get("username",None) pwd = request.POST.get("pwd",None) result["name"] = name result["pwd"] = pwd result = json.dumps(result) return HttpResponse(result,content_type="application/json;charset=utf-8")
b、使用request模块发起POST和GET请求
#Auther Bob #--*--conding:utf-8 --*-- import requests import json class TestCase(object): def __init__(self,username,pwd,url): self.username = username self.pwd = pwd self.url = url def get(self): # 发送get请求 url = self.url + "?username=" + str(self.username) + "&" + "pwd=" + str(self.pwd) res = requests.get(url=url) print(res.text,type(res.text)) def post(self): # 发送post请求 data = { "username" : self.username, "pwd" : self.pwd } res = requests.post(url=self.url,data=data) print(res.text) if __name__ == \'__main__\': url = "http://127.0.0.1:9090/web/login/" username = "zhangsan" pwd = "123" t = TestCase(username,pwd,url) t.get() t.post()
c、这里我们引入unittest框架,测试案例可以这么写
import unittest from test3 import test_request class TestDjango(unittest.TestCase): def setUp(self): print("unittest框架的前置条件") def tearDown(self): print("unittest框架的后置条件") def test_01(self): url = "http://127.0.0.1:9090/web/login/" username = "zhangsan" pwd = "123" t = test_request.TestCase(url=url,username=username,pwd=pwd) def test_02(self): url = "http://127.0.0.1:9090/web/login/" username = "zhangsan" pwd = "123" t = test_request.TestCase(url=url,username=username,pwd=pwd) t.post() if __name__ == \'__main__\': unittest.main(verbosity=2)
d、这里有重复代码,我们可以利用unittest框架中的classmethod来解决,因为实例化一个测试类可以放在前置条件中
import unittest from test3 import test_request class TestDjango(unittest.TestCase): @classmethod def setUpClass(cls): url = "http://127.0.0.1:9090/web/login/" username = "zhangsan" pwd = "123" # 这里的t虽然是类变量,但是python的中的实例是可以用引用类变量的 cls.t = test_request.TestCase(url=url,username=username,pwd=pwd) def setUp(self): print("unittest框架的前置条件") def tearDown(self): print("unittest框架的后置条件") def test_01(self): self.t.get() def test_02(self): self.t.post() if __name__ == \'__main__\': unittest.main(verbosity=2)
e、在testcase中加入断言
import unittest from test3 import test_request class TestDjango(unittest.TestCase): @classmethod def setUpClass(cls): url = "http://127.0.0.1:9090/web/login/" username = "zhangsan" pwd = "123" # 这里的t虽然是类变量,但是python的中的实例是可以用引用类变量的 cls.t = test_request.TestCase(url=url,username=username,pwd=pwd) def setUp(self): print("unittest框架的前置条件") def tearDown(self): print("unittest框架的后置条件") def test_01(self): res = self.t.get() self.assertEqual(200,res.status_code) def test_02(self): res = self.t.post() self.assertEqual(200, res.status_code) if __name__ == \'__main__\': unittest.main(verbosity=2)
f、引入testsuite
import unittest from unittest import TestLoader from test3 import test_unittest if __name__ == \'__main__\': suite = unittest.TestSuite() loader = TestLoader() test_cases1 = unittest.TestLoader().loadTestsFromModule(test_unittest) # 参数是一个模块,会把这个模块里的所有case加载进来 suite.addTests(test_cases1) runner = unittest.TextTestRunner(verbosity=2) runner.run(suite)
二、在django中设计接口
这里我们写一个简单的例子,设计一个用户表,设计4个接口
接口1:登陆
接口2:增加用户,需要用户登陆
接口3:删除用户,需要用户登陆
接口4:查询用户,不需要用户登陆
1、先看登陆接口
a、登录接口对应的url
下面是一级路由
url(r\'^web/\', include(\'unittesstApp1.urls\'))
下面是二级路由
url(r\'^login/\', views.test_login),
b、登录接口的视图函数
def test_login(request): method = request.method.upper() if method == "GET": returndict = {"code": 200, "error": None} username = request.GET.get("username",None) password = request.GET.get("password",None) if username == "admin" and password == "admin123.": request.session["username"] = username request.session["password"] = password result = json.dumps(returndict) else: returndict["code"] = 201 returndict["error"] = "用户名或者密码错误" result = json.dumps(returndict) return HttpResponse(result,content_type="application/json;charset=utf-8")
这里我们用到了session来代替cookies
2、增加用户接口
a、增加用户对应的url
一级路由同登陆接口,下面是二级路由
url(r\'^add/\', views.test_add),
b、增加用户接口对应的视图函数,这里我们做了各种异常处理,且判断了用户是否登陆,也就是通过是否携带cookies来判断
def test_add(request): method = request.method.upper() if method == "POST": returndict = {"code": 200, "error": None} username = request.session.get("username",None) password = request.session.get("password",None) if username == "admin" and password == "admin123.": newusername = request.POST.get("username",None) age = request.POST.get("age",None) sex = request.POST.get("sex",None) pwd = request.POST.get("pwd",None) userinfo = [newusername,age,sex,pwd] print(userinfo) if not "None" in userinfo and all(userinfo): if models.userInfo.objects.filter(username = userinfo[0]).exists(): returndict["error"] = "{username} is exists,please add a new username".format(username = username) returndict["code"] = 201 result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8") else: models.userInfo.objects.create( username = newusername, age = age, sex = sex, pwd = pwd ) if models.userInfo.objects.filter(username=userinfo[0]).exists(): result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8") else: returndict["error"] = "{username} is error,please retry add".format(username=username) returndict["code"] = 201 result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8") else: returndict["error"] = "must input username,age,sex,pwd" returndict["code"] = 201 result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8") else: returndict = {"code": 201, "error": "用户名或者密码错误"} result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8")
3、删除接口
a、删除用户对应的url
一级路由同登陆接口,这里只看二级路由
url(r\'^del/\', views.del_user),
b、删除接口对应的视图函数,这里我做了各种异常处理,也做了用户是否登陆的检测,也是通过检测cookies来实现
def del_user(request): method = request.method.upper() if method == "POST": returndict = {"code": 200, "error": None} username = request.session.get("username",None) password = request.session.get("password",None) if username == "admin" and password == "admin123.": delusername = request.POST.get("username",None) print(delusername) if delusername != None: if models.userInfo.objects.filter(username=delusername).exists(): delid = models.userInfo.objects.get(username=delusername).id print(delid) try: models.userInfo.objects.get(id=delid).delete() except Exception as e: returndict = {"code": 201, "error": e} result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8") else: result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8") else: returndict = {"code": 201, "error": "{username} is not exists".format(username = delusername)} result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8") else: returndict = {"code": 201, "error": "you must input a username"} result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8") else: returndict = {"code": 201, "error": "username or password is error"} result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8")
4、查看接口
a、查看接口对应的url
一级路由同登陆接口url,下面是二级路由
url(r\'^scan/\', views.get_user),
b、查看接口对应的url,这里我们不检测用户是否登陆,直接把查到的数据返回给客户,如果查询报错,才返回错误的信息
def get_user(request): method = request.method.upper() returndict = {"code": 200, "userinfo": None} if method == "GET": try: alluser = models.userInfo.objects.all().values_list("username") alluserlist = [] for i in alluser: alluserlist.append(i) returndict["userinfo"] = alluserlist except Exception as e: returndict["code"] = "201" returndict["error"] = e finally: result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8")
5、设计删除数据库中所有的接口,用来做后置条件
def del_alluser(request): method = request.method.upper() if method == "POST": returndict = {"code": 200, "error": None} username = request.session.get("username", None) password = request.session.get("password", None) if username == "admin" and password == "admin123.": if models.userInfo.objects.all().count() > 0: models.userInfo.objects.all().delete() result = json.dumps(returndict) return HttpResponse(result, content_type="application/json;charset=utf-8")
三、案例准备
1、在excel中写好接口测试案例
2、定义常量,也就是每列对应的值
class TestConfig(object): def __init__(self): self.name = 0 self.url = 1 self.method = 2 self.cookies = 3 self.data = 4 self.res = 5 self.exec = 6 def getname(self): return self.name def geturl(self): return self.url def getmethod(self): return self.method def getcookies(self): return self.cookies def getdata(self): return self.data def getres(self): return self.res def getexec(self): return self.exec
3、定义读取excel的类,因为我要从excel中读取案例
import xlrd import os class testexcel(object): casepath = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "case", "testcase.xlsx") def __init__(self): self.casepath = testexcel.casepath self.execlobj = xlrd.open_workbook(self.casepath) self.sheetobj = self.execlobj.sheet_by_index(0) def get_excel_data(self,row,col): max_row = self.get_excel_max_row() max_col = self.get_excel_max_col() if row > max_row -1 or col > max_col - 1: return False else: data = self.sheetobj.cell_value(row,col) return data def get_excel_max_row(self): r_num = self.sheetobj.nrows return r_num def get_excel_max_col(self): c_num = self.sheetobj.ncols return c_num
4、定义我们的接口函数
import requests import json class TestLogin(object): def __init__(self,username,pwd,url): self.username = username self.pwd = pwd self.url = url def get(self): # 发送get请求 url = self.url + "?username=" + str(self.username) + "&" + "password=" + str(self.pwd) res = requests.get(url=url, headers={ "user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" }) # print(json.loads(res.text)) return res def post(self): # 发送post请求 data = { "username" : self.username, "pwd" : self.pwd } res = requests.post(url=self.url, data=data, headers={ "user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" }, ) # print(res.text) return res class TestAdd(object): def __init__(self,username,age,sex,pwd,cookies,url): self.username = username self.age = age self.sex = sex self.pwd = pwd self.url = url self.cookies = cookies def post(self): # 发送post请求 data = { "username" : self.username, "pwd" : self.pwd, "age" : self.age, "sex" : self.sex } res = requests.post(url=self.url, data=data, headers={ "user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" }, cookies=self.cookies, ) # print(res.text) return res class Testdel(object): def __init__(self, username,cookies,url): self.username = username self.cookies = cookies self.url = url def post(self): # 发送post请求 data = { "username": self.username, } res = requests.post(url=self.url, data=data, headers={ "user-agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" }, cookie以上是关于python自动化测试三部曲之request+django实现接口测试的主要内容,如果未能解决你的问题,请参考以下文章