精华内容
下载资源
问答
  • 本篇文章是接于python接口自动化学习笔记(封装方法用于读取excel) 后的拓展,讲解在封装完成excel的数据读取代码后,如何在data层进行使用首先,我准备了这样一个excel表格用以存储测试数据1、新建data_config文件...

    本篇文章是接于python接口自动化学习笔记(封装方法用于读取excel) 后的拓展,讲解在封装完成excel的数据读取代码后,如何在data层进行使用

    首先,我准备了这样一个excel表格用以存储测试数据

    1、新建data_config文件

    声明所有变量#coding:utf-8

    class global_var:

    #case_id

    id = 0

    url = 1

    request_method = 2

    data = 3

    expected = 4

    #获取case_id

    def get_id():

    return global_var.id

    #获取url

    def get_url():

    return global_var.url

    #获取请求方式

    def get_request_method():

    return global_var.request_method

    #获取请求数据

    def get_data():

    return global_var.data

    #获取预期结果

    def get_expected():

    return global_var.expected

    2、新建get_data文件用以读取测试数据

    封装读取测试数据的代码 封装的目的是为了在调用相应的方法时,可以获取对应的excel中对应字段的值,例如调用get_data(),可以获取到“请求参数”,封装代码如下:#coding:utf-8

    from data import data_config

    from data.operation_excel import OpeExcel

    class GetData:

    def __init__(self):

    self.operation_excel = OpeExcel()

    # 获取excel行数(case个数)

    def get_case_lines(self):

    return self.operation_excel.get_lines()

    # 获取url

    def get_url(self,row):

    col = data_config.get_url()

    url = self.operation_excel.get_value(row,col)

    return url

    # 获取请求方式

    def get_request_method(self, row):

    col = data_config.get_request_method()

    request_method = self.operation_excel.get_value(row, col)

    return request_method

    # 获取请求参数

    def get_data(self, row):

    col = data_config.get_data()

    data = self.operation_excel.get_value(row, col)

    return data

    # 获取请求结果

    def get_expected(self, row):

    col = data_config.get_expected()

    result = self.operation_excel.get_value(row, col)

    return result

    封装完成,可以执行以下代码查看结果,会打印出“请求参数”中第3行的值if __name__ == '__main__':

    data = GetData()

    print(data.get_data(2))

    打印结果:

    展开全文
  • 我相信,认真根据以上文章操作的话,你已经基本掌握了用 Python 在框架上编写简单的自动化脚本了,但是对于项目而言,还是不够的,为了使自动化脚本具有更好的可维护性,那我们开始今天给大家的分享:编写自动化脚本...

    阅读文本大概需要 4.2 分钟。

    最近的系列教程都是讲 Python 自动化相关的,今天这个分享 RF 系列的教程最后一个知识点,讲讲提高脚本编写效率的方式:分层思想。

    我相信,认真根据以上文章操作的话,你已经基本掌握了用 Python 在框架上编写简单的自动化脚本了,但是对于项目而言,还是不够的,为了使自动化脚本具有更好的可维护性,那我们开始今天给大家的分享:编写自动化脚本的分层思想。

    分层思想

    关键字驱动本质上是一种分层思想,「关键字」的底层其实还是程序定义的方法。比如打开浏览器 Open Browser 方法其实就是 RF 框架封装好的打开浏览器的方法,我们直接调用即可。分层思想把一个固定的实现过程分成不同的多层。提高的脚本灵活性,从而达到可扩展性和可维护性。

    基础流程封装

    拿操作浏览器那篇文章中登录 pk 哥博客举例,就登录这个功能,我们简单的设计一个正例和两个反例:

    账号正确,密码正确

    账号正确,密码错误

    账号错误,密码正确

    如果我们直接写的话,我们是不是得写 3 条类似的案例脚本呢?

    5QTLUPVR5E1MYHQP6JJ1-325x200.png

    这样写代码的复用性太差,而且一旦输入框定位方式改了的话,我的就得一条一条的去改,不利于后期维护。其实这些案例,除了账号密码不一样,操作步骤完全一样,所以我们可以利用分层思想,把代码封装起来,封装成关键字,账号和密码作为变量。

    A07FG_9PI_Y8S@Z5TFCY-400x117.png

    我们用 Arguments 列出变量,格式是 ${a},这样脚本封装好了,我们就可以直接调用封装好的方法,并输入必要的参数就可以了。

    @TU_@MTTTA3NKAL@3W-1-400x169.png

    这样脚本是不是变得很简洁了?而且可读性更好了。

    刚才我们是把封装的关键字和脚本放在一个文件里面的,可以直接调用。如果封装的功能块比较多的话,我们可以单独放在另一个文件里面,这样我们调用时需先在 Settings 中用 Resource 命令导入这个文件,这样就可以随意调用这个文件中的任意关键字了。

    OBZX4OK1SFQ81DSH_N2-1-325x200.jpg

    当然,你也可以调用这些基础的操作上再深一层的封装一些稳定的操作或业务供调用,这样后期可以更好的维护脚本。

    参数封装

    大家看过之前写的一篇自动化操作 APP 的文章应该知道,我们启动设备中的 APP 时,需要输入设备 ID 的参数。在团队中,如果是 APP 测试的话,测试部每个测试员都有一台测试手机,如果每次执行脚本时都要去脚本中把参数都改成自己的,有些参数的改动的可能还不止一次,而且还有可能容易漏掉修改。像这样易变动的数据我们可以把它变成参数。

    我们新建一个文件,命名为「参数.robot」,在 Variables 下列出容易变动的参数,比如 Appium 端口号、设备名称。

    2NMWH7BL5X_N97_3VIT-400x118.png

    调用这些参数同样需要先在 Settings 中用 Resource 命令导入这个文件,那么上次 APP 签到的脚本我们就可以修改成这样。

    A9EOY63S5XERUZPDJN2D-400x77.png

    这样的好处是,多处调用的参数我们只需要在文件中改动一次就可以全部生效,这样维护起来就更方便了。

    展开全文
  • # -*- coding:utf-8 -*-'''@project: ApiAutoTest@author: Jimmy@file: ...

    # -*- coding:utf-8 -*-

    '''

    @project: ApiAutoTest

    @author: Jimmy

    @file: http_request.py

    @ide: PyCharm Community Edition

    @time: 2018-12-20 11:38

    @blog: https://www.cnblogs.com/gotesting/

    '''

    import requests

    class HttpRequest:

    def __init__(self,method,url,data=None,cookies=None,headers=None):

    try:

    if method == 'get':

    self.response = requests.get(url=url,params=data,cookies=cookies,headers=headers)

    elif method == 'post':

    self.response = requests.post(url=url,data=data,cookies=cookies,headers=headers)

    elif method == 'detele':

    self.response = requests.delete(url=url,data=data,cookies=cookies,headers=headers)

    except Exception as e:

    raise e

    def get_status_code(self):

    return self.response.status_code

    def get_text(self):

    return self.response.text

    def get_json(self):

    return self.response.json()

    def get_cookies(self):

    return self.response.cookies

    展开全文
  • Python接口自动化之requests请求封装

    千次阅读 热门讨论 2021-07-27 13:41:51
    在上一篇Python接口自动化测试系列文章:Python接口自动化之Token详解及应用,介绍token基本概念、运行原理及在自动化中接口如何携带token进行访问。 以下主要介绍如何封装请求。 还记得我们之前写的get请求、...

    在上一篇Python接口自动化测试系列文章:Python接口自动化之Token详解及应用,介绍token基本概念、运行原理及在自动化中接口如何携带token进行访问。

    以下主要介绍如何封装请求。

    图片

     还记得我们之前写的get请求、post请求么?

    大家应该有体会,每个请求类型都写成单独的函数,代码复用性不强。

    接下来将请求类型都封装起来,自动化用例都可以用这个封装的请求类进行请求,我们将常用的get、post请求封装起来。

    import requests
    class RequestHandler:
        def get(self, url, **kwargs):
            """封装get方法"""
            # 获取请求参数
            params = kwargs.get("params")
            headers = kwargs.get("headers")
            try:
                result = requests.get(url, params=params, headers=headers)
                return result
            except Exception as e:
                print("get请求错误: %s" % e)
        def post(self, url, **kwargs):
            """封装post方法"""
            # 获取请求参数
            params = kwargs.get("params")
            data = kwargs.get("data")
            json = kwargs.get("json")
            try:
                result = requests.post(url, params=params, data=data, json=json)
                return result
            except Exception as e:
                print("post请求错误: %s" % e)
        def run_main(self, method, **kwargs):
            """
            判断请求类型
            :param method: 请求接口类型
            :param kwargs: 选填参数
            :return: 接口返回内容
            """
            if method == 'get':
                result = self.get(**kwargs)
                return result
            elif method == 'post':
                result = self.post(**kwargs)
                return result
            else:
                print('请求接口类型错误')
    if __name__ == '__main__':
        # 以下是测试代码
        # get请求接口
        url = 'https://api.apiopen.top/getJoke?page=1&count=2&type=video'
        res = RequestHandler().get(url)
        # post请求接口
        url2 = 'http://127.0.0.1:8000/user/login/'
        payload = {
            "username": "vivi",
            "password": "123456"
        }
        res2 = RequestHandler().post(url2,json=payload)
        print(res.json())
        print(res2.json())
    

    请求结果如下:

    {'code': 200, 'message': '成功!', 'result': [{'sid': '31004305', 'text': '羊:师傅,理个发,稍微修一下就行', 'type': 'video', 'thumbnail': 'http://wimg.spriteapp.cn/picture/2020/0410/5e8fbf227c7f3_wpd.jpg', 'video': 'http://uvideo.spriteapp.cn/video/2020/0410/5e8fbf227c7f3_wpd.mp4', 'images': None, 'up': '95', 'down': '1', 'forward': '0', 'comment': '25', 'uid': '23189193', 'name': '青川小舟', 'header': 'http://wimg.spriteapp.cn/profile/large/2019/12/24/5e01934bb01b5_mini.jpg', 'top_comments_content': None, 'top_comments_voiceuri': None, 'top_comments_uid': None, 'top_comments_name': None, 'top_comments_header': None, 'passtime': '2020-04-12 01:43:02'}, {'sid': '30559863', 'text': '机器人女友,除了不能生孩子,其他的啥都会,价格239000元', 'type': 'video', 'thumbnail': 'http://wimg.spriteapp.cn/picture/2020/0306/5e61a41172a1b_wpd.jpg', 'video': 'http://uvideo.spriteapp.cn/video/2020/0306/5e61a41172a1b_wpd.mp4', 'images': None, 'up': '80', 'down': '6', 'forward': '3', 'comment': '20', 'uid': '23131273', 'name': '水到渠成', 'header': 'http://wimg.spriteapp.cn/profile/large/2019/07/04/5d1d90349cd1a_mini.jpg', 'top_comments_content': '为游戏做的秀', 'top_comments_voiceuri': '', 'top_comments_uid': '10250040', 'top_comments_name': '不得姐用户', 'top_comments_header': 'http://wimg.spriteapp.cn/profile', 'passtime': '2020-04-11 20:43:49'}]}
    {'token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InZpdmkiLCJleHAiOjE1ODY4NTc0MzcsImVtYWlsIjoidml2aUBxcS5jb20ifQ.k6y0dAfNU2o9Hd9LFfxEk1HKgczlQfUaKE-imPfTsm4', 'user_id': 1, 'username': 'vivi'}
    

    这样就完美了吗,no,no,no。以上代码痛点如下:

    代码量大:只是封装了get、post请求,加上其他请求类型,代码量较大;

    缺少会话管理:请求之间如何保持会话状态。

    图片

    我们再来回顾下get、post等请求源码,看下是否有啥特点。

    get请求源码:

    def get(url, params=None, **kwargs):
        r"""Sends a GET request.
        :param url: URL for the new :class:`Request` object.
        :param params: (optional) Dictionary, list of tuples or bytes to send
            in the query string for the :class:`Request`.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :return: :class:`Response <Response>` object
        :rtype: requests.Response
        """
        kwargs.setdefault('allow_redirects', True)
        return request('get', url, params=params, **kwargs)
    

    post请求源码:

    def post(url, data=None, json=None, **kwargs):
        r"""Sends a POST request.
        :param url: URL for the new :class:`Request` object.
        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
            object to send in the body of the :class:`Request`.
        :param json: (optional) json data to send in the body of the :class:`Request`.
        :param \*\*kwargs: Optional arguments that ``request`` takes.
        :return: :class:`Response <Response>` object
        :rtype: requests.Response
        """
        return request('post', url, data=data, json=json, **kwargs)
    
    

    仔细研究下,发现get、post请求返回的都是request函数。

    既然这样,我们再来研究下request源码:

    def request(method, url, **kwargs):
        """Constructs and sends a :class:`Request <Request>`.
        :param method: method for the new :class:`Request` object.
        :param url: URL for the new :class:`Request` object.
        :param params: (optional) Dictionary, list of tuples or bytes to send
            in the query string for the :class:`Request`.
        :param data: (optional) Dictionary, list of tuples, bytes, or file-like
            object to send in the body of the :class:`Request`.
        :param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
        :param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.
        :param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.
        :param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
            ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
            or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string
            defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
            to add for the file.
        :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.
        :param timeout: (optional) How many seconds to wait for the server to send data
            before giving up, as a float, or a :ref:`(connect timeout, read
            timeout) <timeouts>` tuple.
        :type timeout: float or tuple
        :param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.
        :type allow_redirects: bool
        :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.
        :param verify: (optional) Either a boolean, in which case it controls whether we verify
                the server's TLS certificate, or a string, in which case it must be a path
                to a CA bundle to use. Defaults to ``True``.
        :param stream: (optional) if ``False``, the response content will be immediately downloaded.
        :param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
        :return: :class:`Response <Response>` object
        :rtype: requests.Response
        Usage::
          >>> import requests
          >>> req = requests.request('GET', 'https://httpbin.org/get')
          <Response [200]>
        """
        # By using the 'with' statement we are sure the session is closed, thus we
        # avoid leaving sockets open which can trigger a ResourceWarning in some
        # cases, and look like a memory leak in others.
        with sessions.Session() as session:
            return session.request(method=method, url=url, **kwargs)
    
    源码看起来很长,其实只有三行,大部分是代码注释。从源码中可以看出,不管是get还是post亦或其他请求类型,最终都是调用request函数。

    既然这样,我们可以不像之前那样,在类内定义get方法、post方法,而是定义一个通用的方法,直接调用request函数即可。看起来有点绕,用代码实现就清晰了。

    import requests
    class RequestHandler:
        def __init__(self):
            """session管理器"""
            self.session = requests.session()
        def visit(self, method, url, params=None, data=None, json=None, headers=None, **kwargs):
            return self.session.request(method,url, params=params, data=data, json=json, headers=headers,**kwargs)
        def close_session(self):
            """关闭session"""
            self.session.close()
    if __name__ == '__main__':
        # 以下是测试代码
        # post请求接口
        url = 'http://127.0.0.1:8000/user/login/'
        payload = {
            "username": "vivi",
            "password": "123456"
        }
        req = RequestHandler()
        login_res = req.visit("post", url, json=payload)
        print(login_res.text)
    
    响应结果:
    {
        "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6InZpdmkiLCJleHAiOjE1ODY4Njk3ODQsImVtYWlsIjoidml2aUBxcS5jb20ifQ.OD4HIv8G0HZ_RCk-GTVAZ9ADRjwqr3o0E32CC_2JMLg",
        "user_id": 1,
        "username": "vivi"
    }
    
    这次请求封装简洁实用,当然小伙伴们也可以根据自己的需求自行封装。
    总结:本文主要通过源码分析,总结出一套简洁的请求类封装。

    下一篇:unittest单元测试框架,敬请关注。

    感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

    ① 2000多本Python电子书(主流和经典的书籍应该都有了)

    ② Python标准库资料(最全中文版)

    ③ 项目源码(四五十个有趣且经典的练手项目及源码)

    ④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

    ⑤ Python学习路线图(告别不入流的学习)

    在我的QQ技术交流群里(技术交流和资源共享,广告进来腿给你打断)

    可以自助拿走,群号953306497(备注“csdn111”)群里的免费资料都是笔者十多年测试生涯的精华。还有同行大神一起交流技术哦。

     

    展开全文
  • 之前小编写过Rest-assuert接口测试框架,它是基于java的,那么怎么轻轻松松玩转python接口自动化测试呢?今天小编就写写如何使用python Request进行接口自动测试。学习任何一门技术一门语言,首先要知道从哪些学起,...
  • python接口自动化之请求封装 python接口自动化之请求封装代码示例: #导入requests请求包 import requests #创建request请求方法封装类 class SendRequest: #创建封装请求方法 方法中设置...
  • python接口自动化测试框架结构 ( 第一章) 点击跳转到第一章,你可以知道框架结构!! 前方高能!!正文开始!! 1、在utlis.py封装Excel读写方法 (文件位置跳转第一章看代码结构) 大家需要知道,读取Excel分两种...
  • python接口自动化学习笔记(封装方法用于读取excel)本文是为难得干货文章(是位大佬所写哦)大家好,我是测试君。下面分享一波Python接口自动化文章:本篇是使用xlrd实现的对excel的数据进行读取,xlrd网上demo很多,...
  • 方法一:方法二:
  • 2019 Python接口自动化测试框架实战开发(一)

    万次阅读 多人点赞 2019-06-28 15:55:25
    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!...整个项目分为四个部分:接口基础丶接口开发丶Unittest与接口测试结合以及接口自动化框架从设计到开发 接口基础包括:H...
  • 欢迎关注【无量测试之道】公众号,回复【领取资源】,Python编程学习资源干货、Python+Appium框架APP的UI自动化Python+Selenium框架Web的UI自动化Python+Unittest框架API自动化、资源和代码 免费送啦~文章下方有...
  • 其实不管任何自动化测试方法中博主个人认为测试用例的管理都是非常重要的,有的小伙伴可能习惯于用excel表格去管理用例,用excel表格管理用例的方法博主以前介绍过今天这里呢,博主就介绍一种更为高效用例管理方式...
  • 基于appium的app自动化测试框架基于appium框架的app自动化测试 App自动化测试主要难点在于环境的搭建,appium完全是基于selenium进行的扩展,所以app测试框架也是基于web测试框架开发的 一.设备连接 (即构建 ...appium...
  • 基于appium和python语言封装自动化测试
  • 本篇文章是接于python接口自动化学习笔记(封装方法用于读取excel) 后的拓展,讲解在封装完成excel的数据读取代码后,如何在data层进行使用 首先,我准备了这样一个excel表格用以存储测试数据 1.新建data_config...
  • python接口自动化测试框架---包括请求的封装、数据库操作、多断言、ddt数据驱动、多种请求方式等
  • 本篇讲义将会重点介绍Selenium WebDriver API的封装的概念和方法,以及使用封装进行自动化测试的设计。 WebDriver API 封装 封装的概念 从之前的讲义和学习中,我们知道,WebDriver API的调用以及自动化测试,...
  • python 接口自动化 excel参数化封装

    千次阅读 2018-11-20 14:50:41
    1、定义config 文件  里面定义全局用的参数, 比如下面用到.../usr/bin/python3 # -*- coding: utf-8 -*- import os # 路径配置;项目的路径 BASE_PATH = os.path.dirname( os.path.dirname(os.path.abspath(__...
  • “ 这是一系列文章,总结了使用Python搭建接口测试自动化的心得”接口测试测试领域很大的一块,做好接口测试,那么整个平台的基本流程和功能也就调通了。而接口测试自动化不仅可以减轻重复工作的人力成本,也可以...
  • 因此在编写自动化测试脚本和搭建自动化测试框架时,最好加上日志的收集功能,可以通过日志来定位问题。 正文 相关概念 在自定义日志之前,我们需要了解如下信息: 日志收集器 可以理解为用于收集日志信息的容器; ...
  • 从本期开始,我们会围绕“Python接口自动化”做专题连载,今天开始做第一讲——自动化测试分层。 目录: 1. 1.1.1 单元自动化测试 2. 1.1.2 接口自动化测试 3. 1.1.3 UI自动化测试 现在流行的是金字塔...
  • 软件测试Python自动化测试项目实战...软件测试python全栈自动化测试工程师VIP课程,自动化测试工程师涨薪必备课程,不用辞职一样学,进名企的王牌课程!课程目录1、开学典礼2、为何学了自动化,会涨薪30003、P...
  • 这也是我们即将进行接口自动化测试的第一步。 废话不多说直接上代码吧。 import requests class Requestuil: def __init__(self): pass def request(self,url,method,headers=None,param=None,content_type...
  • python+requests实现接口的请求前篇已经介绍,还有不懂或者疑问的可以访问目前我们需要考虑的是如何实现关键字驱动实现接口自动化输出,通过关键字的封装实现一定意义上的脚本与用例的脱离!robot framework 的安装...
  • 封装的意义在哪里,我们都知道我们每次去调用请求一个接口都是传上面的这些参数,与其这样不如直接将其封装成一个方法,让方法执行完成之后,直接返回整个响应的json体 这就是把对应的请求参数全部使用函数变量来...
  • python+selenium自动化测试封装

    千次阅读 2016-12-29 17:01:40
    测试框架就是一个集成的体系,包括测试功能的函数库(如导入的包),测试数据源(测试数据),测试对象识别标准(webdriver的各个api),以及可充用的模块(结构优化),自动化测试框架主要经过 模块驱动测试--》数据...
  • 一、使用类对post请求和get请求进行封装 1、首先我们来了解一下什么是类及类的作用: class run_main: # 定义一个class类 pass run = run_main() # 创建一个run_main实例 run.post = "POST" # 为实例添加 POST 属性...
  • python教程全解 需要的环境 浏览器(Firefox/Chrome/IE..) Python Selenium Selenium IDE(如果用Firefox) FireBug、FirePath(如果用Firefox) chromedriver、IEDriverServer、phantomjs.exe ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 53,340
精华内容 21,336
关键字:

python测试自动化封装

python 订阅