1. 程式人生 > 程式設計 >python自動化測試三部曲之request+django實現介面測試

python自動化測試三部曲之request+django實現介面測試

國慶期間準備寫三篇部落格,介紹和總結下介面測試,由於國慶期間帶娃,沒有按照計劃完成,今天才完成第二篇,慚愧慚愧。

這裡我第一篇部落格的地址:https://www.jb51.net/article/197004.htm,主要是介紹unittest框架,有興趣的同學們可以移步去查閱

這裡廢話少說,進入正題

我的思路是這樣的

1、先用django實現登陸、增加、刪除、檢視4個介面

2、在excel定義好測試案例、然後讀取excel中的案例,然後把案例用unittest框架組裝和封裝

3、啟動django,執行測試案例

一、先跑通unittest到django的流程

1、先建立一個Django的專案

python自動化測試三部曲之request+django實現介面測試

2、建立路由,這裡我們使用二級路由

a、先複製工程目錄下的urls.py檔案到app目錄下

python自動化測試三部曲之request+django實現介面測試

b、修改工程目錄下的urls.py檔案,定義一級路由

python自動化測試三部曲之request+django實現介面測試

c、修改app目錄下的urls.py檔案,設定二級路由,這裡切記務必要刪除預設的admin這條路由

python自動化測試三部曲之request+django實現介面測試

d、定義這條路由指向的檢視的函式

python自動化測試三部曲之request+django實現介面測試

e、啟動django,這裡我們使用9090埠啟動,因為我們的Jenkins埠用的是8080

E:\python\unittestForDjango>python manage.py runserver 9090

f、這裡的是啟動成功的樣式,我圈住的告警可以忽略,因為這裡Django的admin需要的,我們這裡不會用到django的admin

python自動化測試三部曲之request+django實現介面測試

g、開啟瀏覽器訪問django,我們的一個簡單的Django專案已經跑通

python自動化測試三部曲之request+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,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,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,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,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,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,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,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中寫好介面測試案例

python自動化測試三部曲之request+django實現介面測試

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,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,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,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,cookies=self.cookies,)
    # print(res.text)
    return res


class Testdel(object):
  def __init__(self,url):
    self.username = username
    self.cookies = cookies
    self.url = url

  def post(self):
    # 傳送post請求
    data = {
      "username": self.username,}
    res = requests.post(url=self.url,)
    # print(res.text)
    return res


class Testscan(object):
  def __init__(self,url):
    self.url = url
  def get(self):
    res = requests.get(url=self.url,cookies=None,)
    return res

5、定義測試案例

import unittest
from test3 import test_request
import json
from util import test_json
from util import test_excel
from case import testconfig
import requests

class TestDjango(unittest.TestCase):
  @classmethod
  def setUpClass(cls):
    cls.alldata = test_json.testjson()

  @classmethod
  def tearDownClass(cls):
    url = "http://127.0.0.1:9090/web/login/" + "?username=" + "admin" + "&" + "password=" + "admin123."
    res = requests.get(url=url,like Gecko) Chrome/57.0.2987.133 Safari/537.36"
         })
    url = "http://127.0.0.1:9090/web/delall/"
    requests.post(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"
           },cookies = res.cookies
           )


  def get_cookies(self):
    url = "http://127.0.0.1:9090/web/login/" + "?username=" + "admin" + "&" + "password=" + "admin123."
    res = requests.get(url=url,like Gecko) Chrome/57.0.2987.133 Safari/537.36"
         })
    # print(json.loads(res.text))
    return res.cookies

  @unittest.skip('noexec')
  def test_login_ok(self):
    row = 1
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,configobj.getexec())
    if execstatus == "YES":
      cookiesstatus = excelobj.get_excel_data(row,configobj.getcookies())
      if cookiesstatus == "YES":
        cookies = self.get_cookies()
      else:
        cookies = None
      data = excelobj.get_excel_data(row,configobj.getdata())
      data = json.loads(data)
      url = excelobj.get_excel_data(row,configobj.geturl())
      res = excelobj.get_excel_data(row,configobj.getres())
      method = excelobj.get_excel_data(row,configobj.getmethod())
      if method == "GET":
        testobj = test_request.TestLogin(data["username"],data["pwd"],url)
        resobj = testobj.get()
        self.assertEqual(int(res),json.loads(resobj.text)["code"])

  @unittest.skip('noexec')
  def test_login_pwd_error(self):
    row = 2
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,json.loads(resobj.text)["code"])

  @unittest.skip('noexec')
  def test_login_user_error(self):
    row = 3
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,json.loads(resobj.text)["code"])

  @unittest.skip('noexec')
  def test_user_pwd_error(self):
    row = 4
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,json.loads(resobj.text)["code"])

  @unittest.skip('noexec')
  def test_insert_ok(self):
    row = 5
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,configobj.getmethod())
      if method == "POST":
        testobj = test_request.TestAdd(data["username"],data["age"],data["sex"],url)
        resobj = testobj.post()
        print(json.loads(resobj.text))
        self.assertEqual(int(res),json.loads(resobj.text)["code"])

  @unittest.skip('noexec')
  def test_insert_nologin(self):
    row = 6
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,json.loads(resobj.text)["code"])

  @unittest.skip("noexec")
  def test_insert_user_error(self):
    row = 7
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,configobj.getmethod())
      if method == "POST":
        testobj = test_request.TestAdd(data.get("username",None),data.get("age",data.get("sex",data.get("pwd",json.loads(resobj.text)["code"])

  @unittest.skip('no exec')
  def test_insert_pwd_error(self):
    row = 8
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,json.loads(resobj.text)["code"])

  @unittest.skip("no exec")
  def test_insert_sex_error(self):
    row = 9
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,configobj.getdata())
      print(data)
      data = json.loads(data)
      print(data)
      url = excelobj.get_excel_data(row,json.loads(resobj.text)["code"])

  @unittest.skip('no exec')
  def test_insert_age_error(self):
    row = 10
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,url)
        resobj = testobj.post()
        print(resobj.text)
        print(json.loads(resobj.text))
        self.assertEqual(int(res),json.loads(resobj.text)["code"])

  @unittest.skip('no exec')
  def test_insert_user_exist(self):
    row = 11
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,json.loads(resobj.text)["code"])

  def test_get_user(self):
    row = 12
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,configobj.getcookies())
      if cookiesstatus == "YES":
        cookies = self.get_cookies()
      else:
        cookies = None

      url = excelobj.get_excel_data(row,configobj.getmethod())
      if method == "POST":
        testobj = test_request.Testscan(url)
        resobj = testobj.get()
        # print(resobj.text
        print(json.loads(resobj.text))
        self.assertEqual(int(res),json.loads(resobj.text)["code"])

  @unittest.skip('no exec')
  def test_del_user(self):
    row = 13
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,configobj.getmethod())
      if method == "POST":
        testobj = test_request.Testdel(data.get("username",json.loads(resobj.text)["code"])


  def test_del_noexistuser(self):
    row = 14
    configobj = testconfig.TestConfig()
    excelobj = test_excel.testexcel()
    execstatus = excelobj.get_excel_data(row,json.loads(resobj.text)["code"])

6、引入unittest的suit,組織案例

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)

四、執行案例

1、啟動django

E:\python\unittestForDjango>python manage.py runserver 9090
Performing system checks...

System check identified no issues (0 silenced).
October 19,2019 - 22:46:42
Django version 1.11.7,using settings 'unittestForDjango.settings'
Starting development server at http://127.0.0.1:9090/
Quit the server with CTRL-BREAK

2、執行測試套件

test_del_noexistuser (test3.test_unittest.TestDjango) ... {"username":"test1"}
{'username': 'test1'}
ok
test_del_user (test3.test_unittest.TestDjango) ... skipped 'no exec'
test_get_user (test3.test_unittest.TestDjango) ... {"code": 201,"error": "test1 is not exists"}
{'code': 201,'error': 'test1 is not exists'}
{'code': 200,'userinfo': []}
ok
test_insert_age_error (test3.test_unittest.TestDjango) ... skipped 'no exec'
test_insert_nologin (test3.test_unittest.TestDjango) ... skipped 'noexec'
test_insert_ok (test3.test_unittest.TestDjango) ... skipped 'noexec'
test_insert_pwd_error (test3.test_unittest.TestDjango) ... skipped 'no exec'
test_insert_sex_error (test3.test_unittest.TestDjango) ... skipped 'no exec'
test_insert_user_error (test3.test_unittest.TestDjango) ... skipped 'noexec'
test_insert_user_exist (test3.test_unittest.TestDjango) ... skipped 'no exec'
test_login_ok (test3.test_unittest.TestDjango) ... skipped 'noexec'
test_login_pwd_error (test3.test_unittest.TestDjango) ... skipped 'noexec'
test_login_user_error (test3.test_unittest.TestDjango) ... skipped 'noexec'
test_user_pwd_error (test3.test_unittest.TestDjango) ... skipped 'noexec'

----------------------------------------------------------------------
Ran 14 tests in 1.466s

OK (skipped=12)

到此這篇關於python自動化測試三部曲之request+django實現介面測試的文章就介紹到這了,更多相關request django 介面測試內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!