51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 1379|回复: 1
打印 上一主题 下一主题

Python做接口自动化测试

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2018-5-31 16:22:09 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
框架结构如下:

Test_Api_Project
|
|---base.py
|---base_api
|   |---register_api.py

|   |---send_sms_code_api.py
|---settings.py
|---test_case
|   |---test_register_api.py

|---utilities

|  |---conn_db.py

|  |---user.py



一、先说settings配置文件,与WEB端自动化类似,settings文件中存放整个项目的配置,如:被测项目
域名、数据库地址、redis地址、APP版本号、请求头等。

复制代码
1 # env config
  1. <p> 2 ENV = 'test'</p><p> 3 </p><p> 4 APP_VERSION = '2.3.7'</p><p> 5 </p><p> 6 HEADERS = {'content-type': 'application/x-www-form-urlencoded; charset=UTF-8'}</p><p> 7 </p><p> 8 # test url test config</p><p> 9 API_TEST_BASE_URL = "http://api.abc.com"</p><p>10 </p><p>11 # redis config</p><p>12 REDIS_HOST = ''</p><p>13 REDIS_PORT = ''</p><p>14 </p><p>15 # mysql config</p><p>16 DB_HOST = ''</p><p>17 DB_PORT = ''</p><p>18 DB_USER = ''</p><p>19 DB_PASSWORD = ''</p><p>复制代码</p><p>二、base.py</p><p>
  2. </p><p>该文件中主要是对测试url的处理、对常用的请求类型重新封装(如:GET、POST等)</p><p>
  3. </p><p>复制代码</p><p> 1 # -*- coding:utf-8 -*-</p><p> 2 import json,requests</p><p> 3 import settings</p><p> 4 </p><p> 5 </p><p> 6 class BaseApi(object):</p><p> 7     url = ""</p><p> 8     base_url= settings.API_TEST_BASE_URL</p><p> 9 </p><p>10     def __init__(self,url_params=None):</p><p>11         if not url_params:</p><p>12             url_params = []</p><p>13         self.url_params = url_params</p><p>14         self.response = None</p><p>15         self.base_url = self.base_url</p><p>16 </p><p>17     # 拼接url</p><p>18     def api_url(self):</p><p>19         if not self.url:</p><p>20             raise RuntimeError("no url been set")</p><p>21         return self._get_url()</p><p>22 </p><p>23     def _get_url(self):</p><p>24         format_url = self.url.format(self.url_params)</p><p>25         return "{0}{1}".format(self.base_url, format_url)</p><p>26 </p><p>27     # 封装POST请求类型</p><p>28     def post(self, data=None):</p><p>29         if not data:</p><p>30             data = {}</p><p>31         base_param = self.build_base_param()</p><p>32         custom_param = self.build_custom_param(data)</p><p>33         data.update(base_param)</p><p>34         data.update(custom_param)</p><p>35         self.response = requests.post(url=self.api_url(), data=data, headers=settings.HEADERS)</p><p>36         return self.response</p><p>37 </p><p>38     # 封装GET请求类型</p><p>39     def get(self,data=None):</p><p>40         if not data:</p><p>41             data={}</p><p>42         base_param = self.build_base_param()</p><p>43         custom_param = self.build_custom_param(data)</p><p>44         data.update(base_param)</p><p>45         data.update(custom_param)</p><p>46         response = requests.get(url=self.api_url(),params=data)</p><p>47         return self.response</p><p>48 </p><p>49     # 获取回参中状态码</p><p>50     def get_code(self):</p><p>51         if self.response:</p><p>52             return json.loads(self.response.text)['code']</p><p>53 </p><p>54     # 获取HTTP状态码</p><p>55     def get_status_code(self):</p><p>56         if self.response:</p><p>57             return self.response.status_code</p><p>58 </p><p>59     # 获取回参中message</p><p>60     def get_response_message(self):</p><p>61         if self.response:</p><p>62             return json.loads(self.response.text)['msg']</p><p>63 </p><p>64     # 所有接口共有的入参,比如:app_version、token等</p><p>65     def build_base_param(self):</p><p>66         return {</p><p>67                 "app_version": SETTINGS.APP_VERSION,</p><p>68                 "token":""</p><p>69         }</p><p>70 </p><p>71     # 被测接口除公共参数外所需的其余参数</p><p>72     def build_custom_param(self, data):</p><p>73         return {}</p><p>复制代码</p><p>三、conn_db.py 连接数据库</p><p>
  4. </p><p>复制代码</p><p> 1 import pymysql.cursors,settings</p><p> 2 </p><p> 3 </p><p> 4 def execute(sql, params=None, db='', is_fetchone=True):</p><p> 5     # Connect to the database</p><p> 6     connection = pymysql.connect(host=settings.DB_HOST,</p><p> 7                                  port=settings.DB_PORT,</p><p> 8                                  user=settings.DB_USER,</p><p> 9                                  password=settings.DB_PASSWORD,</p><p>10                                  db=db,</p><p>11                                  autocommit=True,</p><p>12                                  charset='utf8mb4',</p><p>13                                  cursorclass=pymysql.cursors.DictCursor)</p><p>14     try:</p><p>15         with connection.cursor() as cursor:</p><p>16             cursor.execute(sql, params)</p><p>17             if is_fetchone:</p><p>18                 return cursor.fetchone()</p><p>19             else:</p><p>20                 return cursor.fetchall()</p><p>21     finally:</p><p>22         connection.close()</p><p>复制代码</p><p>user.py文件主要是对数据库中用户相关的一些操作</p><p>
  5. </p><p>复制代码</p><p># -*- coding:utf-8 -*-</p><p>import db</p><p>
  6. </p><p>def get_sms_captcha(mobile):</p><p>    # 获取短信验证码</p><p>    sms_captcha = db.execute('select code from send_sms_code where mobile=%s order by id desc',p</p><p>arams=(mobile))</p><p>    return sms_captcha['code']</p><p>
  7. </p><p>def delete_user(mobile):</p><p>    # 删除用户</p><p>    db.execute('delete from user where mobile=%s',params=(mobile))</p><p>复制代码</p><p> </p><p>
  8. </p><p>
  9. </p>
复制代码

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1
回复

使用道具 举报

该用户从未签到

2#
 楼主| 发表于 2018-5-31 16:22:47 | 只看该作者
  1. <p>四、下面以注册接口为例子</p><p>
  2. </p><p>因注册时需要获取短信验证码,所以除了调用注册接口之外,还需要调用获取短信验证码皆苦,在base_</p><p>api下新建register_api.py、send_sms_code_api.py,内容如下:</p><p>
  3. </p><p>register_api.py</p><p>
  4. </p><p>复制代码</p><p> 1 # -*- coding:utf-8 -*-</p><p> 2 from base_api.base_api import BaseApi</p><p> 3 import settings</p><p> 4 </p><p> 5 class RegisterApi(BaseApi):</p><p> 6     url = '/home/register'</p><p> 7     </p><p> 8     #对BaseApi类中build_custom_param方法重写</p><p> 9     def build_custom_param(self, data):</p><p>10         return {'login_name':data['login_name'],'password':data['password'],'code':data['code'],'nickname':data['nickname']}</p><p>复制代码</p><p>send_sms_code_api.py</p><p>
  5. </p><p>复制代码</p><p> 1 # -*- coding:utf-8 -*-</p><p> 2 from base_api.base_api import BaseApi</p><p> 3 import settings</p><p> 4 </p><p> 5 </p><p> 6 class SendSmsCaptcha(BaseApi):</p><p> 7     url = '/user/sendsms'</p><p> 8 </p><p> 9     def build_custom_param(self, data):</p><p>10         return {'type': data['type'], 'phone': data['phone']}</p><p>复制代码</p><p>对两个接口的url地址和所需要的入参都已经封装好了,接下来开始写case。</p><p>
  6. </p><p> </p><p>
  7. </p><p>在test_case下新建test_register_api.py</p><p>
  8. </p><p>下面是一个注册成功的例子</p><p>
  9. </p><p>复制代码</p><p> 1 # -*- coding:utf-8 -*-</p><p> 2 from unittest import TestCase</p><p> 3 from base_api.register_api import RegisterApi</p><p> 4 from base_api.send_sms_code_api import SendSmsCaptcha</p><p> 5 from utilities import user</p><p> 6 import settings,json</p><p> 7 </p><p> 8 </p><p> 9 </p><p>10 class TestRegisterApi(TestCase):</p><p>11     new_mobile = '13000000001'</p><p>12     password = '123abc'</p><p>13     nick_name = 'XiangXi'</p><p>14 </p><p>15 </p><p>16     def test_register_success(self):</p><p>17         # 调用发送短信验证码接口</p><p>18         send_sms_code_api = SendSmsCaptcha()</p><p>19         send_sms_code_api.post({'type':'register','phone':self.new_mobile})</p><p>20 </p><p>21         # 校验发送短信验证码接口HTTP状态码为200</p><p>22         self.assertEqual(send_sms_code_api.get_status_code(),200)</p><p>23 </p><p>24         # 校验发送短信验证码接口反参中code为0,代表成功(不同项目该字段值不一定为0)</p><p>25         self.assertEqual(send_sms_code_api.get_code(),0)</p><p>26 </p><p>27         # 通过数据库获取短信验证码</p><p>28         sms_code = user.get_sms_captcha(self.new_mobile)</p><p>29 </p><p>30         # 调用注册接口</p><p>31         register_api = RegisterApi()</p><p>32         response = register_api.post({'login_name':self.new_mobile,'password':self.password,'code':sms_code,'nickname':self.nick_name})</p><p>33 </p><p>34         # 校验注册接口HTTP状态码为200</p><p>35         self.assertEqual(send_sms_code_api.get_status_code(),200)</p><p>36 </p><p>37         # 校验注册接口反参中code为0</p><p>38         self.assertEqual(register_api.get_code(),0)</p><p>39 </p><p>40         # 校验反参中手机号、登录名与用户昵称是否与入参值一样</p><p>41         identity_obj = json.loads(response.content)['result']['identity_obj']</p><p>42         self.assertEqual(identity_obj['nickname'],self.nick_name)</p><p>43         self.assertEqual(identity_obj['login_name'],self.new_mobile)</p><p>44         self.assertEqual(identity_obj['mobilephone'],self.new_mobile)</p><p>45 </p><p>46     def tearDown(self):</p><p>
  10. </p><p>47         user.delete_user(self.new_mobile)</p><p>复制代码</p>
复制代码



最后和WEB端类似,通过teardown()方法将新注册的用户在数据库中删除,防止该手机号下次执行ca
se时候报手机号已被注册。

为了更好了验证通过接口注册的用户信息,也可以调用登录接口测试一下注册接口反参中的用户名是
否可以正常登陆返回token。



五、如果调用接口的前提需要用户登录,那么就需要BaseApi类中build_base_param方法中的token有
一个有效的值,否则调用接口时可能会提示token错误或者用户未登录等,这种情况下可以新建一个
LoginBaseApi类,继承BaseApi,代码如下:

假设对登录接口已经进行了封装,入参为login_name和password

复制代码
1 # -*- coding:utf-8 -*-
  1. <p> 2 from base_api.base_api import BaseApi</p><p> 3 from base_api.login_api import LoginApi</p><p> 4 </p><p> 5 class LoginBaseApi(BaseApi):</p><p> 6     def __init__(self, login_name,password, *args, **kwargs):</p><p> 7         super(LoginBaseApi, self).__init__(*args, **kwargs)</p><p> 8         self.login_name = login_name</p><p> 9         self.password = password</p><p>10 </p><p>11     def build_base_param(self):</p><p>12         base_param = super(LoginBaseApi, self).build_base_param()</p><p>13         response = LoginApi().post(self.login_name, self.password)</p><p>14         base_param['token'] = token</p><p>15         return base_param</p>
复制代码

复制代码


这时,底层类就有两个,一个是BaseApi() 一个是LoginBaseApi(),需要登录的接口在封装入参时继承Login
BaseApi,不需要登录的接口继承BaseApi



回复 支持 反对

使用道具 举报

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

GMT+8, 2024-11-18 04:46 , Processed in 0.065200 second(s), 26 queries .

Powered by Discuz! X3.2

© 2001-2024 Comsenz Inc.

快速回复 返回顶部 返回列表