精华内容
下载资源
问答
  • UI自动化源码
  • python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口自动化测试python 接口...
  • 如何使用python自动化脚本

    千次阅读 2020-12-03 14:03:59
    小编就有这样的感觉,事实上,脚本确实真的很厉害,能解决我们软件运行的大小问题,比如游戏时候,脚本也是很常见的哦下面就教大家写脚本,一起来学习下吧 准备工具: 安装python 安装教程点击...

    第一次听到脚本,会不会觉得特别厉害呢?小编就有这样的感觉,事实上,脚本确实真的很厉害,能解决我们软件运行的大小问题,比如游戏时候,脚本也是很常见的哦下面就教大家写脚本,一起来学习下吧

    准备工具:

    安装python 安装教程点击https://www.py.cn/jishu/jichu/20465.html

    安装selenium 安装教程点击https://www.py.cn/jishu/jichu/20358.html

    注意事项:

    l selenium3.0需要独立安装Firefox驱动,不再自带驱动,下载地址: https://github.com/mozilla/geckodriver/releases 下载对应版本,解压放在python安装路径下即可;

    l geckodriver驱动要求Friefox浏览器必须48版本以上,如果不是,更新Firefox;

    l 如果用Java开发,需注意3.0必须用JDK1.8版本才行;

    l Chromedriver下载:https://sites.google.com/a/chromium.org/chromedriver/downloads 同样也是下载后放在python安装路径下即可。

    编写自动化脚本:

    完成上面所有准备工作,就可以开始第一个自动化脚本的编写啦~

    打开IDLE,通过快捷键ctrl+n打开一个新窗口,在新窗口输入以下代码:

    from selenium import webdriver
     
    browser = webdriver.Firefox()
     
    browser.get("http://www.baidu.com")
     
    browser.find_element_by_id("kw").send_keys("selenium")
    browser.find_element_by_id("su").click()
     
    browser.quit()
    

    保存为test1.py,通过快捷键F5运行脚本,可看到脚本启动Firefox 浏览器进入百度页,输入“selenium” 点击搜索按钮,最后关闭浏览器的过程。脚本即完成了~

    为了防止乱码问题,以及在程序中添加中文注释,把编码统一成 UTF-8;

    from selenium import webdriver
    

    导入selenium的webdriver包,导入webdriver包后才能使用 webdriver API 进行自动化脚本开发;

    browser = webdriver.Firefox()
    

    将控制的 webdriver 的 Firefox 赋值给 browser;获得了浏览器对象才可以启动浏览器;

    browser.get("http://www.baidu.com")
    

    获得浏览器对象后,通过 get()方法,向浏览器发送网址;

    browser.find_element_by_id("kw").send_keys("selenium")
    

    通过 id=kw 定位到百度的输入框,并通过键盘方法send_keys()向输入框里输入selenium ;

    browser.find_element_by_id("su").click()
    

    通过 id=su 定位到搜索按钮,并向按钮发送单击事件(click() ) ;

    browser.quit()
    

    退出并关闭窗口的每一个相关的驱动程序。

    好了,大家也可以试试哦,准备工具非常的少,也特别容易操作上手~

    展开全文
  • Appium是一个开源测试自动化框架,可用于原生,混合和移动Web应用程序测试, 它使用WebDriver协议驱动iOS,Android和Windows应用程序。 通过Appium,我们可以模拟点击和屏幕的滑动,可以获取元素的id和classname,...
  • Python编写自动化脚本(无验证码)

    千次阅读 热门讨论 2019-05-04 22:28:05
    x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"} login(username,password) study() #运行study函数的时候会自动运行apply函数,所以不需要再写apply() 注:视频文件无法刷成功...

    、模拟登陆
    打开登陆界面,F12,打开开发者工具(大部分浏览器都自带),选择Network,如果没有显示,就把该页面刷新一下
    我这里登陆的网站是 http://x.x.x.x/?q=custom_user_login
    在这里插入图片描述

    输入账号,密码(这里我的密码填写的1,用做测试),原本很短的密码却变得很长,这里我们就有一个猜想,这里的password值在客户端进行了加密,所以我们右键审查该password表单元素
    在这里插入图片描述
    在这里插入图片描述
    由上图可知这里果然进行了加密,于是我们把下图中type="password"的password删除,查看密码明文,看看他究竟是怎么进行加密的
    在这里插入图片描述
    在这里插入图片描述
    由上图看出1被加密成了32位16进制数,并且根据上图中的hex_md5,于是猜想他是md5加密,以hex(16进制)显示,在 https://www.cmd5.com/ 进行验证
    在这里插入图片描述
    由上图可知,他果然是在前端进行了一次md5加密
    随后我们进行一次正确的登陆,获取账号密的变量名,如下图:
    在这里插入图片描述

    现在开始编写第一段代码,登陆账号:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    # Author:1stPeak
    
    import requests
    import hashlib
    import re
    
    request = requests.Session()   #requests库的session对象能够帮我们跨请求保持某些参数,也会在同一个session实例发出的所有请求之间保持cookies
    
    def login(username,password):
        login_url = "http://x.x.x.x/?q=custom_user_login"
        md = hashlib.md5()
        md.update(password.encode('utf-8'))
        password = md.hexdigest()
        data = {"username": username,
                "password": password}
        try:
            req = request.post(login_url,data=data,headers=header)
            req.encoding = 'utf-8'
            #print(req.text)   #这个用来测试是否登陆成功(查看登陆前与登录后的源代码有何差别)
            if "请输入注册时填写的手机号" not in req.text:
              print("登陆成功")
            else:
              print("登录失败")
        except:
            print("未知错误")
            
    if __name__ == '__main__':
        username="你的用户名"
        password="你的密码"
        header = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"}
        login(username,password)
    

    、申请课程

    • 打开burpsuite,开始抓包,再点击报名学习
      在这里插入图片描述
      在这里插入图片描述

    • 抓到下图的POST请求(申请课程请求)
      请求url为/?q=node/75827/people/apply
      在这里插入图片描述

    • 输入url后打开
      在这里插入图片描述
      在这里插入图片描述

    • 再打开 http://x.x.x.x/?q=node/75827, 检验是否申请成功
      在这里插入图片描述
      申请课程代码段:

    apply_url="http://x.x.x.x/?q=node/75926/people/apply"
        req = request.get(apply_url,headers=header)
        #print(req.text)
        try:
            if "message" in req.text:
                print("申请成功")
            else:
                print("申请失败")
        except:
            print("未知错误")
    

    为了可以申请更多的课程,我们修改一下代码:

    def apply():
        for i in range(75926,75927):
            apply_url = "http://x.x.x.x/?q=node/"+str(i)+"/people/apply"
            try:
                req = request.get(apply_url,headers=header)
                if "success" in req.text:
                    print(str(i)+"课程申请成功")
                    return i
            except:
                print(str(i) + "申请失败")
    

    、刷课程

    study = "http://x.x.x.x/?q=items/student/study/75926"
        try:
            req = request.get(study, headers=header)
            req.encoding = 'utf-8'
            G = r'<a score=".*?" uid=".*?" title=".*?" class="itemtitle" nid=".*?" module_id=".*?" item_id=".*?" href="/(.*?)">.*?</a>'
            study = re.findall(G,req.text)
            for study_url_last in study:
                study_url_all = "http://39.106.4.51/" + study_url_last
                try:
                    request.get(study_url_all,headers=header,timeout=4)
                    print(study_url_all+"刷课成功")
                except:
                    print(study_url_all+"刷课失败")
        except:
            pass
    

    为了可以刷更多的课程,我们来完善一下代码:

    def study():
        study_url = "http://x.x.x.x/?q=items/student/study/"+str(apply())
        try:
            req = request.get(study_url,headers=header)
            req.encoding='utf-8'
            G = r'<a score=".*?" uid=".*?" title=".*?" class="itemtitle" nid=".*?" module_id=".*?" item_id=".*?" href="/(.*?)">.*?</a>'
            study_url_list = re.findall(G,req.text,re.M|re.S)
            for study_url_last in study_url_list:
                study_url_all = "http://39.106.4.51/" + study_url_last
                try:
                    req = request.get(study_url_all,headers=header,timeout=4)
                    print(study_url_all+"学习完成")
                except:
                    print(study_url_all+"学习失败")
        except:
            pass
    

    、完整代码:

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    # Author:1stPeak
    
    import requests
    import hashlib
    import re
    
    request = requests.Session()   #requests库的session对象能够帮我们跨请求保持某些参数,也会在同一个session实例发出的所有请求之间保持cookies
    
    def login(username,password):
        login_url = "http://x.x.x.x/?q=custom_user_login"
        md = hashlib.md5()
        md.update(password.encode('utf-8'))
        password = md.hexdigest()
        data = {"username": username,
                "password": password}
        try:
            req = request.post(login_url,data=data,headers=header)
            req.encoding = 'utf-8'
            #print(req.text)   #这个用来测试是否登陆成功(查看登陆前与登录后的源代码有何差别)
            if "请输入注册时填写的手机号" not in req.text:
              print("登陆成功")
            else:
              print("登录失败")
        except:
            print("未知错误")
            
    def apply():
        for i in range(75926,75927):
            apply_url = "http://x.x.x.x/?q=node/"+str(i)+"/people/apply"
            try:
                req = request.get(apply_url,headers=header)
                if "success" in req.text:
                    print(str(i)+"课程申请成功")
                    return i
            except:
                print(str(i) + "申请失败")
                
    def study():
        study_url = "http://x.x.x.x/?q=items/student/study/"+str(apply())
        try:
            req = request.get(study_url,headers=header)
            req.encoding = 'utf-8'
            G = r'<a score=".*?" uid=".*?" title=".*?" class="itemtitle" nid=".*?" module_id=".*?" item_id=".*?" href="/(.*?)">.*?</a>'
            study_url_list = re.findall(G,req.text,re.M|re.S)
            for study_url_last in study_url_list:
                study_url_all = "http://39.106.4.51/" + study_url_last
                try:
                    request.get(study_url_all, headers=header, timeout=6)
                    print(study_url_all + "学习完成")
                except:
                    print(study_url_all + "学习失败")
        except:
            pass
            
    if __name__ == '__main__':
        username="你的用户名"
        password="你的密码"
        header = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"}
        login(username,password)
        study()   #运行study函数的时候会自动运行apply函数,所以不需要再写apply()
    

    注:视频文件无法刷成功,电脑自己看一遍还是不能完成任务点,不知其原因,如有知道或解决办法,请评论留言,Thank you~

    更新:此次文章仅供学习参考,不再更新。

    其他图片:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • Python 编写自动化工具

    万次阅读 多人点赞 2017-08-29 00:41:44
    但是假如我们要做跨平台的开发,根据每个平台去开发一套功能相同的自动化脚本显然不是最好的选择,选择跨平台通用的脚本是更好的选择,Python 就是常用来编写自动化工具的跨平台脚本语言。Python 环境安装:1.资源...

    引言:

    在开发过程中,我们经常需要编写一些自动化的工具,例如:

    • Windows 下的 BATCH (批处理)
    • Linux 下的 Shell

    但是假如我们要做跨平台的开发,根据每个平台去开发一套功能相同的自动化脚本显然不是最好的选择,选择跨平台通用的脚本是更好的选择,Python 就是常用来编写自动化工具的跨平台脚本语言。

    Python 环境安装:

    1.资源下载:

    直接到 Python 官网 下载安装包,有两个分支:2.x 和 3.x,两者有着巨大的差别,当然现在比较流行的还是 2.7.x 系列,这里我直接下载此系列的最新版本:python-2.7.13.msi

    2.安装步骤:

    过程十分简单,双击打开安装包,一直 Next 直到安装完成,记得要记录一下其安装目录,后面配置系统环境时要用到。

    3.环境配置:

    打开 计算机 -> 属性 -> 高级系统设置 -> 环境变量... ,然后再 系统变量 中新建一项,设置参数如下:

    变量名:PYTHON_HOME
    变量值:D:\Develope\Python2.7
    

    然后编辑系统变量中的 Path 变量的参数,在变量值最后加上 ;%PYTHON_HOME%;,然后保存编辑内容。然后,打开命令行窗口查询是否配置成功:

    C:\Users\hasee-pc>python --version
    Python 2.7.13
    

    以上说明环境变量的配置已完成。

    4.运行 Python:

    运行 Python 代码块的方式有两种,一种是直接在命令行窗口输入 Python 指令进入交互式编程窗口,然后直接输入代码,键盘 Enter 执行结果,如下:

    C:\Users\hasee-pc>python
    Python 2.7.13 (v2.7.13:a06454b1afa1, Dec 17 2016, 20:42:59) [MSC v.1500 32 bit (
    Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    >>> print "hi,linsh"
    hi,linsh
    

    也可以创建一个 .py 脚本,编辑好脚本内容,例如:

    # test.py
    print "hi,linsh"
    

    然后,在命令行定位到脚本所在目录,执行该脚本,以下两种执行方式都可以:

    D:\Develope\PythonProjects>python test.py
    hi,linsh
    D:\Develope\PythonProjects>test.py
    hi,linsh
    

    # 号用于注释单行,多行注释通常使用三引号 '''""" 开始和结束。


    Python 基础语法:

    这里不会赘述太多细节性的语法,只简述一些必要的基础语法,更详细的可以参考 【 Python 语言参考 】:

    1.特殊标识符:

    • 跟其他编程语言一样,Python 中所有标识符可以包含:英文、数字以及下划线(_),但不能以数字开头;
    • 以下划线开头的表示特殊含义:
      • 单下划线 _ 开头表示不能直接被外部类直接访问的类属性,,需要通过类提供的接口才能进行访问,例如:_foo
      • 双下划线 __ 开头表示类的私有成员,就像很多语言中的 private 权限关键字的作用,例如:__foo
      • 以双下划线开头和结尾代表 Python 中特殊方法专用的标识,例如 __init__() 代表类的构造函数。

    2.缩进和代码块:

    Python 与其他语言最大的不同,在于它不使用 {} 或者像 Lua 那样的关键字来包裹一个代码块以管理类、函数或逻辑判断,而是直接通过 缩进 来管理模块。

    缩进的空白 数量(键盘空格键次数)是可变的,但是所有代码块语句必须包含相同的缩进空白数量。例如:

    if True:
        print "True"
    else:
      	print "False"
    

    通常将编程工具的一次 Tab 键的距离设为 4 个空格 距离,作为一级缩进的空白数。

    3.数据类型和变量:

    Python 有 5 种标准的数据类型:

    Numbers(数字)
    String(字符串)
    List(列表)
    Tuple(元组)
    Dictionary(字典)
    

    但是,在定义变量时,不需要声明变量的类型,变量在使用前需要先进行赋值,此时解释器才能根据赋值的类型为此变量分配创建内存空间并创建此变量,只是声明但不赋值的变量是不能使用的。例如:

    number = 2	    # 整型
    percent = 100.0	# 浮点型
    name = "linsh"	# 字符串
    

    此外,还可以同时对多个变量进行赋值:

    number,percent,name = 2,100.0,"linsh"
    

    4.函数:

    函数的使用一方面是为了提高代码的重用性,另一方面又可以增强代码的可读性和模块化,下面是 Python 定义函数的格式:

    def funcName(param1,param2,...):
    	...
    

    以关键字 def 来声明一个函数,紧跟着是函数名(函数标识符),然后是 () 包围起来的传入参数表,可以是 0 个参数,也可以是多个参数,然后用 : 号开始函数内容的开始。例如:

    # test.py
    # # -*- coding: utf-8 -*-
    
    # 方法定义
    def TestFunc1():
    	print "test1"
    
    def TestFunc2(num):
      	print "test2: num = ",num #str 和 int 类型拼接
        
    # 方法调用
    TestFunc1()
    TestFunc2(66)
    

    执行结果:

    D:\Develope\PythonProjects>test.py
    test1
    test2: num =  66
    

    编写工具:

    1.设计目标:

    首先说一下我要工具的功能:

    遍历某个目录下包括其下子目录中所有指定的后缀文件,然后为这些文件的头部插入指定的字符串。

    2.使用场景:

    设计这样的工具起因是我最近在将之前 CSDN 中的博客搬运到自己的 Hexo 博客空间上,了解的应该知道,假如都是 Markdown 编写的话,搬运的时候只需要在文件头部加上如下的一串额外的内容:

    ---
    title: 博客标题
    date: 博客创建时间(例如:2016-09-03 17:15:22)
    tags: 标签(如:[Hexo,Next],多个的话用,号隔开)
    categories: 分类(如:Web)
    ---
    
    • 标题 title 直接使用文件名称去掉 .md 后缀即可;
    • 时间 date 需要通过文件库获取文件的创建时间;
    • 标签 tags 和分类 categories ,由于我的文件会根据分类放入不同的子目录下,所以直接获取当前文件所在目录的名称即可。

    此外,为了在博客首页只展示部分内容,而不是展开博客的完整内容,还需要在博客中恰当的位置插入这个标签:<!--more--> ,通常加载第一段内容结束的位置。

    3.实现代码:

    根据上面的思路,我们在 source/_posts 目录下创建一个工具脚本,起名为 SuitFileToHexo.py ,然后依次完成以下步骤:

    • 指定 Linux 环境下 Python 解释器目录,并指定编码方式:

      #!/usr/bin/env python
      # -*- coding: utf-8 -*-
      
    • 引入的模块:

      在脚本开始的地方,最先需要做的事情就是把需要用到的模块都先引入进来,大致分析一下我们这个功能需要用到的模块:

      import os.path,time
      
    • 遍历当前目录下所有 .md 文件列表:

      这就需要使用到 Python 的文件目录操作模块 os.path ,使用 os.listdir 获取目录列表,然后通过 os.path.splitext 分割文件名称和后缀名,从而筛选合格的文件:

      # 获取指定目录指定后缀名的文件列表
      def getFileList(path,endStr):
      	'''获取指定目录下,指定后缀的文件列表'''
      	r_list = []
      	f_list = os.listdir(path)	#获取目录列表
      	for i in f_list:
      		# 分离文件名和后缀名,过滤掉工具脚本
      		file_endStr = os.path.splitext(i)[1]
      		# 判断是否是目录
      		if os.path.isdir(i):
      			f_list1 = os.listdir(path+'/'+i)
      			for j in f_list1:
      				# 过滤出指定后缀 endStr 后缀的文件
      				if os.path.splitext(j)[1] == endStr:
      					# 为了清晰目录把文件所在目录也标识出来
      					r_list.append(i+'/'+j)
      					# print j.decode("string_escape")
      		elif file_endStr == endStr:
      			r_list.append(i)
      	return r_list
      

    这里发现了一个问题,就是在 os.path.isdir(i) 在 2.7.11 的版本莫名其妙地返回 false,需要做如下修改才能正常:

     if file_endStr == '':
         i = os.path.join(path, i)   #=================〉这一行很必要
    	 # print i
    	 # 判断是否是目录
    	 if os.path.isdir(i):
    	     ...
    
    • 获取文件的创建时间:

      需要使用到 os.time 模块的功能:

      # 获取文件创建时间
      def get_FileCreateTime(filePath):
      	  t = os.path.getctime(filePath)
      	  return TimeStampToTime(t)
      
      # 把时间戳转化为时间: 1479264792 to 2016-11-16 10:53:12'''
      def TimeStampToTime(timestamp):
      	  timeStruct = time.localtime(timestamp)
      	  return time.strftime('%Y-%m-%d %H:%M:%S',timeStruct)
      
    • 获取博客标题:

      其实就是从目录字符串中截掉后缀名,再截掉最后一个 / 之前的内容即可得到博客名称:

      # 获取目录中去掉前面路径和后缀的文件名字
      def getFileSimpleName(filePath):
          name = ''
          # 先去掉后缀
      	  name = os.path.splitext(filePath)[0]
      	  # 获取最后一个斜杠位置
      	  index = name.rfind('/')
      	  # 找不到则返回 -1
      	  if index != -1:
      	  # 截取斜杠后面到结尾内容
      	  name = name[index+1:]
      	  # print name
      	  return name
      
    • 获取文件所在的目录名称作为页签值:

      与获取博客名称思路略有相似,获取最后一个斜杠位置,截掉斜杠之后的内容,在获取一个最后一个斜杠位置,假如有则截取斜杠之后的内容即是文件所在目录的名称:

      # 获得分类文件目录名称
      def getTypeNameByPath(filePath):
      	fileTag = ''
      	# 获取最后一个斜杠位置
      	index = filePath.rfind('/')
      	# 找不到则返回 -1
      	if index != -1:
      		# 截取斜杠后面到结尾内容
      		fileTag = filePath[:index]
      		# 截掉前面部分
      		index = fileTag.rfind('/')
      		if index != -1:
      			fileTag = fileTag[index+1:]
      	# print fileTag
      	return fileTag
      
    • 向文件中插入内容:

      调用以上方法即可分别得到我们想要的信息:

      # 指定目录
      path = './'
      # 得到文件列表
      files = getFileList(path,'.md')	
      for i in files:
          print 'title: '+getFileSimpleName((i.decode("string_escape")))
          print 'date: '+get_FileCreateTime((path+i.decode("string_escape")))
          print 'tags: ['+getTypeNameByPath((i.decode("string_escape")))+']'
      

      接下来要做的就是把这些内容按照格式插入到文件中去,当然插入之前需要先检查文件中是否已经插入过类似的内容了,可以简单地通过检查开头 40 个字符串中是否包含这个字符串来判别:

    ‘’’—
    title: ‘’’

    
    关于展示分隔符 ``<!--more-->`` 插入的位置,大致逻辑是:第一个标题后面,而且刚好插入在第二个标题之前即可,而使用 Markdown 语法撰写的博客标题使用 ``#`` 来表示的,最终的插入方法如下:
    
    ```python
    # 向文件中插入指定数据
    def addHeadToFile(filePath,title,date,tags):
    	file = open(filePath,"r")
    	content = file.read()
    	index = content[:40].find('''---
    title:''')
    	# 添加
    	if index == -1:
    		print 'Undadded'
    		addContent = '''---
    title: '''+title+'''
    date: '''+date+'''
    tags: ['''+tags+''']
    categories: '''+tags+'''
    ---
    '''
    		# 检测是否插入部分显示标签
    		content = addContent + content
    		index = content.find('''<!--more--> ''')
    		if index == -1:
    			# 获取第一段的位置
    			index = content.find('''### ''')
    			if index != -1:
    				#print "first ### pos = ",index
    				# 下一个标题位置(在第二个标题之前插入即可)
    				pos = content[index:].find('''
    
    #''',1)
    				if pos != -1:
    					index += pos
    					#print "second enter pos = ",index
    					content = content[:index]+'''
    <!--more-->
    '''+content[index:]
    		file = open(filePath,"w")
    		file.write(content)
    	else:
    		#print 'file head had added'
    	# 记得要关闭文件
    	file.close()
    

    最后完整的调用过程:

    # 指定目录
    path = './'
    # 得到文件列表
    files = getFileList(path,'.md')	
    # 声明一些全局变量
    title = ''
    date = ''
    tags = ''
    for i in files:
        	title = getFileSimpleName(i.decode("string_escape"))
        	date = get_FileCreateTime(path+i.decode("string_escape"))
        	tags = getTypeNameByPath(i.decode("string_escape"))
        	print 'title: '+title
        	print 'date: '+date
        	print 'tags: ['+tags+']'
        	addHeadToFile(path+i.decode("string_escape"),title,date,tags)
    

    其他:

    如果你跟我一样出现了打印中文文件名变成诸如: “BATCH\xc5\xfa\xb4\xa6\xc0\xed\xbc\xf2\xbc\xc7.md” 这种格式的话,可以参考:Linux 下Python2.7解决list打印中文字符问题


    参考资料:


    微信公众号「何乐不为呢」,一个码农的技术笔记和唠叨。

    展开全文
  • 自动化脚本编写实例-python

    万次阅读 多人点赞 2017-07-03 13:32:15
    自动化脚本编写实例

    自动化脚本编写实例

    完整demo请参看:https://github.com/niununu/k2p_web_test

    本文以修改用户名密码单元为案例,编写测试脚本。完成修改用户名密码模块单元测试。

    (ps.这个demo中登陆密码为“admin”)

    1. 打开浏览器,访问p.to

    # 1. 打开浏览器,访问p.to
    driver = webdriver.Chrome()
    def openDriver():
        driver.get("http://p.to")
        driver.maximize_window()

    2. 登陆

    登陆这动作传入的参数只有一个“用户密码”

    需要执行的操作有两个:1. 向输入框输入密码 2. 点击确定

    需要注意的是在登陆的时候可能出现页面还没有加载出来,我们的程序就开始填写表单的情况。

    为了防止异常出现,编写了函数waitandSendkeys和waitandClick来处理异常。(后面将会介绍异常处理函数)

    class loginClass(object):
        """docstring for login"""
        def __init__(self, arg):
            self.login_pwd = arg
        def login(self):
            waitandSendkeys('//*[@id="Pwd"]', self.login_pwd)
            waitandClick('//*[@id="Save"]')

    3. 修改管理员密码

    需要传入的参数有两个:1.旧密码 2. 新密码

    要注意的是由于修改管理员密码是一个弹窗,所以要判断等弹窗弹出之后再进行操作

    class changePwdClass(object):
        """docstring for changePwdClass"""
        def __init__(self, pwdNew, pwdOld):
            self.pwdNew = pwdNew        
            self.pwdOld = pwdOld
    
        def changeUserPwd(self):
            waitandClick('//*[@id="Con"]/div[1]/ul[2]/li[1]')
            waitandClick('//*[@id="Con"]/div[1]/ul[2]/li[1]/ul/li[3]')
            waitforDisplay('//*[@id="_Widget"]')
            waitandSendkeys('//*[@id="PwdOld"]', self.pwdOld)
            waitandSendkeys('//*[@id="PwdNew"]', self.pwdNew)
            waitandSendkeys('//*[@id="PwdCfm"]', self.pwdNew)
            waitandClick('//*[@id="SavePwd"]')

    到这里,我们可以完成修改用户名密码这一动作。后面将进行单元测试。

    4. 单元测试数据

    修改用户名密码这个功能的防呆规则如下:

    输入项允许输入可为空格式规范合法性依赖项
    原管理员密码字符串长度限制:5-63; 字符集:英文字符集;需要与管理员密码相同
    新管理员密码字符串长度限制:5-63; 字符集:英文字符集;
    确认管理员密码字符串需要与新管理员密码相同

    根据防呆规则可以列出:1.可能出现的错误 2.出现错误时页面应有的提示语

    #可能出现的错误
    errcode = ['oldPwdErr', 'lenErr', 'charErr', 'matchErr', 'pwdSameErr',\
        'oldPwdBlankErr', 'newPwdBlankErr']
    
    #出现错误时页面应有的提示语
    errTips = {
        'oldPwdErr' :'原密码错误',
        'lenErr' : '新密码长度应为5~63位',
        'charErr' : "新密码包含非法字符",
        'matchErr' : '两次密码输入不一致',
        'pwdSameErr' : '新密码与原密码相同,请重新输入',
        'oldPwdBlankErr' : '请输入原密码',
        'newPwdBlankErr' : '请输入新密码'
    }

    5. 检查输入的数据合法性

    需要输入的数据为要检查的data和登陆密码

    def checkData(data, loginPwd):#检查顺序跟页面顺序相同
        pwd = loginPwd
        #'oldPwdBlankErr'
        if data['pwdOld'] == "":
            return errcode[5]
        #newPwdBlankErr
        if data['pwdNew'] == "":
            return errcode[6]
        #charErr
        strTmp = data['pwdNew']
        for x in xrange(0,len(data['pwdNew'])):
            if ord(strTmp[x]) < 33 or ord(strTmp[x]) > 127:#ASCII表示范围:32-127
                return errcode[2]
        #lenErr
        if len(data['pwdNew']) > 63 or len(data['pwdNew']) < 5:
            return errcode[1]
        #oldPwdErr
        if pwd != loginData.login_data['login_pwd']:
            return errcode[0]
        #pwdSameErr
        if data['pwdNew'] == pwd:
            return errcode[4]
        #no error
        return None

    6. 获取输入错误数据之后的页面提示语

    def checkResponse(error):
        if error == None:
            return
    
        webText = getText('//*[@id="PwdTip"]')
        if webText == False:#没有提示
            print('###Error: no tips on web!')
        else:
            webText = webText.decode('UTF-8')
        waitandClick('//*[@id="ModifyPwd"]/i')
        time.sleep(1)
        return webText

    7. 编写测试用例

        data = [
            {"pwdNew" : "12345678","pwdOld" : '8dadla'},#"oldPwdErr"
            {"pwdNew" : "admi","pwdOld" : 'admin'},#lenErr
            {'pwdNew' : '1  2  3','pwdOld' : 'admin'},#charErr
            {'pwdNew' : 'admin','pwdOld' : 'admin'},#pwdSameErr
            {'pwdNew' : "",'pwdOld' : ""},#oldPwdBlank
            {'pwdNew' : "",'pwdOld' : "admin"}#newPwdBlank
        ]

    8.编写单元测试类

    8.1 单元测试中的通用操作

    单元测试中,不同的部分应该是数据,所以可以定义一个通用的操作。

    其中self.assertEqual(checkResponse(error), errTips[error])是判定测试是否通过的条件:页面提示语是否正确。

    def commonAction(self, arg):
            error = checkData(arg)
            changeUserPwd.main(arg)
            self.assertEqual(checkResponse(error), errTips[error])

    8.2 测试类

    测试类中主要包括了测试用例6个,和对应的以“test”开头的测试函数。

    这里继承了python的unittest。

    关于unittest的语法请参考:http://www.jb51.net/article/65856.htm

    class TestCase(unittest.TestCase):
        data = [
            {"pwdNew" : "12345678","pwdOld" : '8dadla'},#"oldPwdErr"
            {"pwdNew" : "admi","pwdOld" : '*'},#lenErr
            {'pwdNew' : '1  2  3','pwdOld' : '*'},#charErr
            {'pwdNew' : 'admin','pwdOld' : '*'},#pwdSameErr
            {'pwdNew' : "",'pwdOld' : ""},#oldPwdBlank
            {'pwdNew' : "",'pwdOld' : "*"}#newPwdBlank
        ]
    
        def commonAction(self, arg):
            error = checkData(arg)
            changeUserPwd.main(arg)
            self.assertEqual(checkResponse(error), errTips[error])
    
        def test_oldPwdErr(self):
            self.commonAction(self.data[0])
        def test_lenErr(self):
            self.commonAction(self.data[1])
        def test_charErr(self):
            self.commonAction(self.data[2])
        def test_pwdSameErr(self):
            self.commonAction(self.data[3])
        def test_oldPwdBlank(self):
            self.commonAction(self.data[4])
        def test_newPwdBlank(self):
            self.commonAction(self.data[5])

    9. 进行单元测试并生成测试报告

    这里利用了HTMLTestRunner来生成测试报告。

    HTMLTestRunner语法请参看:https://testerhome.com/topics/7576

    生成的测试报告将会存放在reports/test_report文件夹下,按照时间命名。测试报告的title叫做“修改管理员密码试报告”

    unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='test_report',report_title='修改管理员密码试报告'))

    10. 关闭浏览器

    def closeDriver():
        time.sleep(3)
        driver.quit()
        os.system('killall chromedriver')
        os.system('killall geckodriver')

    到这里,我们可以完成修改用户名密码模块的单元测试了,为了增加代码的健壮性,下面介绍异常处理。

    11. 异常处理

    11.1 点击函数

    点击按钮的时候可能出现的异常情况是:可能页面元素还没有加载出来的时候,点击的动作就发生了。这样就会引发找不到元素异常。

    解决的方法是通过显示等待,每10ms检查一次页面元素是否加载完成,完成后就点击,否则就等到超时时间之后结束动作。

    def waitandClick(xpath):
        try:
            WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, xpath)))
        except TimeoutException as e:
            print('Error:waitandClick, TimeoutException, xpath = %s\n' % xpath)
        else:
            driver.find_element_by_xpath(xpath).click()

    11.2 填写表单

    在填写表单时,除了页面元素还没有加载完成的异常外,还可能原有表单中有文本,而我们的输入则是以追加模式填写的。这就会导致填写的文本不准确。

    def waitandSendkeys(xpath, keys):
        try:
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, xpath)))
        except TimeoutException as e:
            print('Error:waitandSendkeys, TimeoutException, xpath = %s\n' % xpath)
        else:
            driver.find_element_by_xpath(xpath).clear()
            driver.find_element_by_xpath(xpath).send_keys(keys)

    11.3 元素加载

    在元素加载中可能出现: 1. 在超时时间内元素没有加载完成 2. 查询的元素根本不存在

    针对这两种情况进行异常处理:

    def waitforDisplay(xpath):
        try:
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, xpath)))
        except TimeoutException as e:
            print('Error:waitforDisplay, TimeoutException, xpath = %s\n' % xpath)
        else:
            try:
                process = driver.find_element_by_xpath(xpath)
                WebDriverWait(driver, 10).until(lambda driver: process.is_displayed())
            except NoSuchElementException as e:
                print('Error:waitforDisplay, NoSuchElementException, xpath = %s\n' % xpath)

    12. 测试报告和代码示例

    12.1 测试报告样例

    demo

    12.2 完整的测试代码

    # -*- coding: UTF-8 -*-
    #!/usr/bin/env python
    
    from selenium import webdriver
    
    import time, os
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium.common.exceptions import NoSuchElementException
    from selenium.common.exceptions import TimeoutException
    
    import unittest
    import HtmlTestRunner
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8') 
    
    
    # 1. 打开浏览器,访问p.to
    driver = webdriver.Chrome()
    def openDriver():
        driver.get("http://p.to")
        driver.maximize_window()
    
    # 2. 登陆
    class loginClass(object):
        """docstring for login"""
        def __init__(self, arg):
            self.login_pwd = arg
    
        def login(self):
            waitandSendkeys('//*[@id="Pwd"]', self.login_pwd)
            waitandClick('//*[@id="Save"]')
    
    def login(data):
        openDriver()
        test1 = loginClass(data)
        test1.login()
    
    # 3.修改管理员密码
    class changePwdClass(object):
        """docstring for changePwdClass"""
        def __init__(self, arg):
            self.pwdNew = arg.get('pwdNew', '')
            self.pwdOld = arg.get('pwdOld', '')
    
        def changeUserPwd(self):
            waitandClick('//*[@id="Con"]/div[1]/ul[2]/li[1]')
            waitandClick('//*[@id="Con"]/div[1]/ul[2]/li[1]/ul/li[3]')
            waitforDisplay('//*[@id="_Widget"]')
            waitandSendkeys('//*[@id="PwdOld"]', self.pwdOld)
            waitandSendkeys('//*[@id="PwdNew"]', self.pwdNew)
            waitandSendkeys('//*[@id="PwdCfm"]', self.pwdNew)
            waitandClick('//*[@id="SavePwd"]')
    
    def changeUserPwd_main(data):
        changePwdObj = changePwdClass(data)
        changePwdObj.changeUserPwd()
    
    # 4. 单元测试数据
    errcode = ['oldPwdErr', 'lenErr', 'charErr', 'matchErr', 'pwdSameErr',\
        'oldPwdBlankErr', 'newPwdBlankErr']
    errTips = {
        'oldPwdErr' :'原密码错误',
        'lenErr' : '新密码长度应为5~63位',
        'charErr' : "新密码包含非法字符",
        'matchErr' : '两次密码输入不一致',
        'pwdSameErr' : '新密码与原密码相同,请重新输入',
        'oldPwdBlankErr' : '请输入原密码',
        'newPwdBlankErr' : '请输入新密码'
    }
    
    # 5. 检查输入的数据合法性
    def checkData(data):#检查顺序跟页面顺序相同
        #pwd = loginPwd
        pwd='admin'
        #'oldPwdBlankErr'
        if data['pwdOld'] == "":
            return errcode[5]
        #newPwdBlankErr
        if data['pwdNew'] == "":
            return errcode[6]
        #charErr
        strTmp = data['pwdNew']
        for x in xrange(0,len(data['pwdNew'])):
            if ord(strTmp[x]) < 33 or ord(strTmp[x]) > 127:#ASCII表示范围:32-127
                return errcode[2]
        #lenErr
        if len(data['pwdNew']) > 63 or len(data['pwdNew']) < 5:
            return errcode[1]
        #oldPwdErr
        if pwd != data['pwdOld']:
            return errcode[0]
        #pwdSameErr
        if data['pwdNew'] == data['pwdOld']:
            return errcode[4]
        #no error
        return None
    
    # 6. 获取输入错误数据之后的页面提示语
    def checkResponse(error):
        if error == None:
            return
        # webText = driver.find_element_by_xpath('//*[@id="PwdTip"]').text
        webText = getText('//*[@id="PwdTip"]')
        if webText == False:#没有提示
            print('###Error: no tips on web!')
        else:
            webText = webText.decode('UTF-8')
        waitandClick('//*[@id="ModifyPwd"]/i')
        return webText
    
    # 8.单元测试类
    class TestCase(unittest.TestCase):
        # 7. 编写测试用例
        data = [
            {"pwdNew" : "12345678","pwdOld" : '8dadla'},#"oldPwdErr"
            {"pwdNew" : "admi","pwdOld" : 'admin'},#lenErr
            {'pwdNew' : '1  2  3','pwdOld' : 'admin'},#charErr
            {'pwdNew' : 'admin','pwdOld' : 'admin'},#pwdSameErr
            {'pwdNew' : "",'pwdOld' : ""},#oldPwdBlank
            {'pwdNew' : "",'pwdOld' : "admin"}#newPwdBlank
        ]
    
        def commonAction(self, arg):
            error = checkData(arg)
            changeUserPwd_main(arg)
            self.assertEqual(checkResponse(error), errTips[error])
            time.sleep(1)
    
        def test_oldPwdErr(self):
            self.commonAction(self.data[0])
        def test_lenErr(self):
            self.commonAction(self.data[1])
        def test_charErr(self):
            self.commonAction(self.data[2])
        def test_pwdSameErr(self):
            self.commonAction(self.data[3])
        def test_oldPwdBlank(self):
            self.commonAction(self.data[4])
        def test_newPwdBlank(self):
            self.commonAction(self.data[5])
    
    # 10. 关闭浏览器
    def closeDriver():
        time.sleep(3)
        driver.quit()
        os.system('killall chromedriver')
        os.system('killall geckodriver')
    
    # 11. 异常处理
    ## 11.1 点击函数
    def waitandClick(xpath):
        try:
            WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, xpath)))
        except TimeoutException as e:
            print('Error:waitandClick, TimeoutException, xpath = %s\n' % xpath)
        else:
            driver.find_element_by_xpath(xpath).click()
    
    ## 11.2 填写表单
    def waitandSendkeys(xpath, keys):
        try:
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, xpath)))
        except TimeoutException as e:
            print('Error:waitandSendkeys, TimeoutException, xpath = %s\n' % xpath)
        else:
            driver.find_element_by_xpath(xpath).clear()
            driver.find_element_by_xpath(xpath).send_keys(keys)
    
    ## 11.3 元素加载
    def waitforDisplay(xpath):
        try:
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, xpath)))
        except TimeoutException as e:
            print('Error:waitforDisplay, TimeoutException, xpath = %s\n' % xpath)
        else:
            try:
                process = driver.find_element_by_xpath(xpath)
                WebDriverWait(driver, 10).until(lambda driver: process.is_displayed())
            except NoSuchElementException as e:
                print('Error:waitforDisplay, NoSuchElementException, xpath = %s\n' % xpath)
    
    def elementIsDisplayed(xpath):
        try:
            driver.find_element_by_xpath(xpath)
        except NoSuchElementException as e:
            return False
    
    def getText(xpath):
        time.sleep(1)
        return driver.find_element_by_xpath(xpath).text
    
    if __name__ == '__main__':
        openDriver()
        login('admin')
        #data = {'pwdNew'='admin', 'pwdOld'='12345678'}
        #changeUserPwd_main(data)
        #9. 进行单元测试并生成测试报告
        unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='test_report',report_title='修改管理员密码试报告'))
        closeDriver()
    
    展开全文
  • Selenium Python 提供了一个简单的API 便于我们使用 Selenium WebDriver编写 功能/验收测试。 通过Selenium Python的API,你可以直观地使用所有的 Selenium WebDriver 功能 。Selenium Python提供了一个很方便的接口...
  • 我们实际跑自动化脚本的过程中,是需要用脚本调用appium启动app的,接下来就尝试写Python脚本启动app并登陆app。环境为Windows10 + Python3.7 + appium1.18.0 + Android手机 + 今日头条app + Pycharm 一,连接测试...
  • 安装pytest的allure的支撑插件 D:\Program Files\Python38\Scripts>pip install allure-pytest 2、首先我们在运行项目文件的时候先创建一个allure报告存放的路径(生成allure的一些xml文件) 3、在执行pytest命令式...
  • python+request+unittest+HTMLTestRunner 框架,从测试到结果
  • 对于很多刚开始写自动化测试脚本的人来说,很容易把所有的代码工具都放在一个代码模块中,使代码看起来杂乱无章,很繁琐,今天分享搭建简单自动化脚本框架,对代码进行封装,这样如果我们要更改代码就不要改几遍或者...
  • python 写第一个自动化脚本的过程

    千次阅读 2018-11-30 21:06:34
    安装好python ,又用pip命令安装好selenium后,用python 自带的IDE编辑 好以下代码:   ①很快遇到了第一个错误提示:'geckodriver' executable needs to be in PATH 我安装的最新的selenium是3以上的版本了,...
  • (给Python开发者加星标,提升Python技能) 原创:Python开发者(id:PythonCoder) 5 月 31 日,1 个法国程序员 Nicolas Beauvais...1 个自动化脚本能搞死公司? 这是什么情况? 根据 Nicolas 发的帖子,我们整理如下
  • 如何将python文件做成自动化脚本 工作过程中有可能会将.py文件做成脚本,例如自动化运维,封装代码 步骤: 1 - 设置shebang符号,指定改文件执行的编译器 2 - 生成执行文件对应的软链接(绝对路径) 3 - 给软链接增加...
  • 运维自动化,已经成为运维必不可少的一部分,下面附上自己写的监控nginx_status脚本,大神轻喷#! usrbinpython#coding:utf-8importurllib.requestimportsocket#自动获取主机ip地址myname=socket.getfqdn(...
  • 安装selenium包,安装Chrome浏览器,安装chromedriver Mac下相关安装: pip install selenium 使用selenium打开一个空的浏览器窗口: from selenium import webdriver driver = webdriver.Chrome() ...
  • 通过Python脚本自动巡检网络设备,并将巡检结果输出到附件,邮件发送。使用的是Python的telnetlib模块
  • Python自动化运维脚本实例

    万次阅读 2018-12-23 17:28:47
    一、用python写一个列举当前目录以及所有子目录下的文件,并打印出绝对路径   #!/usr/bin/env python import os for root,dirs,files in os.walk('/tmp'):  for name in files:  print (os.path.join(root...
  • 五、Python编写接口自动化

    万次阅读 多人点赞 2018-06-08 19:17:02
    (2)、引用py脚本 (3)、robot使用 (4)输出结果 5. 参见问题: (1)、python接口能返回结果,但在获取结果里的data值却报错了(string indices must be integers) 原因是接口返回结果没有转换转成obj  原...
  • 本已收会围绕整个开发过程,从配置和规划到自动化测试和创建不同的命令行工具。本书涵盖了基础脚本到标准库Python包使用都所有常用知识。通过本书的学习,你将了解如何基于理想的资源规划、实施和发...
  • 基于Android的Appium+Python自动化脚本编写 1.Appium Appium是一个开源测试自动化框架,可用于原生,混合和移动Web应用程序测试, 它使用WebDriver协议驱动iOS,Android和Windows应用程序。 通过Appium,我们可以...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 74,452
精华内容 29,780
关键字:

python编写自动化脚本

python 订阅