专栏首页北京宏哥《手把手教你》系列进阶篇之4-python+ selenium自动化测试 - python几种超神操作你都知道吗?(详细教程)

《手把手教你》系列进阶篇之4-python+ selenium自动化测试 - python几种超神操作你都知道吗?(详细教程)

1. 简介

  今天分享和讲解的超神操作,对于菜鸟来说是超神的操作,对于大佬来说也就是几个简单方法的封装和调用。这里讲解和分享这部分主要是为了培养小伙伴们和童鞋们的面向对象的开发思维,对比这样做的好处让你自己身临其境的感受一番。

2. 自定义封装一个简单的Log类

  本文介绍如何写一个Python日志类,用来输出不同级别的日志信息到本地文件夹下的日志文件里。为什么需要日志输出呢,我们需要记录我们测试脚本到底做了什么事情,最好的办法是写事件监听。这个事件监听,对我们现在来说,还是有点复杂去理解,所以我这里,选择封装一个简单的日志类,同样达到这个效果。

我们大概需要如下日志输出效果:

2.1 问题分析:

我们需要封装一个简单的日志类,主要有以下内容:

1. 生成的日志文件格式是 年月日时分秒.log

2. 生成的xxx.log文件存储在项目根目录下Logs文件夹下

3. 这个日志类,支持INFO,ERROR两种日志级别

4. 日志里,每行日志输出,如上图,时间日期+执行类名称+日志级别+日志描述

2.2 解决问题思路:

1. 在根目录下新建一个Logs的文件夹,如何获取这个Log的相对路径,前面介绍过。

2. 日志的保存命名,需要系统时间,前面也介绍过时间格式化输出

3. Python中有一个logging模块来支持我们自定义封装一个新日志类。

4. 在脚本里,初始化一个日志类的实例对象,然后去控制输出INFO还是ERROR日志信息。

自定义日志类封装如下:logger.py,新建在test包下

2.3 代码实现:

2.4 参考代码:

# coding=utf-8?

# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行

# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2019-12-16
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之4-python+ selenium自动化测试 - python基础扫盲
'''

# 3.导入模块

import logging
import os.path
import time


class Logger(object):

    def __init__(self, logger):
        """
        指定保存日志的文件路径,日志级别,以及调用文件
        将日志存入到指定的文件中
        :param logger:
        """
        # 创建一个logger
        self.logger = logging.getLogger(logger)
        self.logger.setLevel(logging.DEBUG)

        # 创建一个handler,用于写入日志文件
        rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
        print(os.getcwd())
        log_path = (os.path.dirname(os.getcwd() + '\\Logs\\'))
        print(log_path)
        log_name = log_path + rq + '.log'
        fh = logging.FileHandler(log_name)
        fh.setLevel(logging.INFO)

        # 再创建一个handler,用于输出到控制台
        ch = logging.StreamHandler()
        ch.setLevel(logging.INFO)

        # 定义handler的输出格式
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)

        # 给logger添加handler
        self.logger.addHandler(fh)
        self.logger.addHandler(ch)

    def getlog(self):
        return self.logger

2.5 新建日志测试类

新写一个测试日志类,相关代码如下:

2.5.1 代码实现:
2.5.2 参考代码:
# coding=utf-8?

# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行

# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2019-12-16
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之4-python+ selenium自动化测试 - python基础扫盲
'''

# 3.导入模块
import time
from selenium import webdriver
from test1.logger import Logger

mylogger = Logger(logger='test_log').getlog()


class TestMyLog(object):

    def print_log(self):
        driver = webdriver.Chrome()
        mylogger.info("打开浏览器")
        driver.maximize_window()
        mylogger.info("最大化浏览器窗口。")
        driver.implicitly_wait(8)

        driver.get("https://www.baidu.com")
        mylogger.info("打开百度首页。")
        time.sleep(1)
        mylogger.info("暂停一秒。")
        driver.quit()
        mylogger.info("关闭并退出浏览器。")


testlog = TestMyLog()
testlog.print_log()
2.5.3 运行结果:

运行代码后,控制台打印如下图的结果

2.5.4 文件保存结果:

运行代码后,在Logs文件夹下可以看到日志文件,如下图的结果

在PyCharm里运行下这个测试类,会在根目录下的Logs文件下,新建一个日志文件,打开效果如文章开头的日志输出图。好了,关于自定义封装log类,自己好好去读下代码,理解下每行代码的意思,日志类的封装和调用就介绍到这里。

3. 把截图类方法封装到前面的BasePage.py

本文介绍把截图类方法封装到BasePage.py文件里,这个文件是在前面Selenium方法二次封装文章里创建的,具体代码请到前面这篇里找。我们截图类写死了把截图图片保存到根目录下的Screenshots文件夹里,图片名称是当前系统时间,图片后缀名是png。

新的BasePage.py内容如下:

3.1 代码实现:

3.2 参考代码:

# coding=utf-8?

# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行

# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2019-12-16
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之4-python+ selenium自动化测试 - python基础扫盲
'''

# 3.导入模块

import os
import time

from test1.logger import Logger

mylog = Logger(logger='BasePage').getlog()
class BasePage(object):
    """
    主要是把常用的几个Selenium方法封装到BasePage这个类,我们这里演示以下几个方法
    back()
    forward()
    get()
    quit()
    """

    def __init__(self, driver):
        """
        写一个构造函数,有一个参数driver
        :param driver:
        """
        self.driver = driver

    def back(self):
        """
        浏览器后退按钮
        :param none:
        """
        self.driver.back()

    def forward(self):
        """
        浏览器前进按钮
        :param none:
        """
        self.driver.forward()

    def open_url(self, url):
        """
        打开url站点
        :param url:
        """
        self.driver.get(url)

    def quit_browser(self):
        """
        关闭并停止浏览器服务
        :param none:
        """
        self.driver.quit()

    def take_screenshot(self):
        """
        截图并保存在根目录下的Screenshots文件夹下
        :param none:
        """
        file_path = os.path.dirname(os.getcwd()) + '/Screenshots/'
        rq = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))
        screen_name = file_path + rq + '.png'
        try :
            self.driver.get_screenshot_as_file(screen_name)
            mylog.info("开始截图并保存")

        except Exception as e:
            mylog.error("出现异常",format(e))

3.3 新建截图类

主要看最后一个截图类方法的封装。

测试类相关代码如下:

3.3.1 代码实现:
3.3.2 参考代码:
# coding=utf-8?

# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行

# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2019-12-16
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之4-python+ selenium自动化测试 - python基础扫盲
'''

# 3.导入模块
import time
from selenium import webdriver

from blog.basepage import BasePage


class TestScreenshot(object):
    driver = webdriver.Chrome()
    driver.maximize_window()
    driver.implicitly_wait(10)
    basepage = BasePage(driver)

    def test_take_screen(self):
        self.basepage.open_url("https://www.baidu.com")
        time.sleep(1)
        self.basepage.take_screenshot()
        self.basepage.quit_browser()

test = TestScreenshot()
test.test_take_screen()
3.3.3 运行结果:

运行代码后,控制台打印如下图的结果

3.3.4 截图保存结果:

运行代码后,在Screenshots文件夹下可以看到截图文件,如下图的结果

运行后,可以在根目录下Screenshots文件夹里找到百度首页截图。

本文就介绍了截图类方法添加到BasePage里,介绍了如何保存到根目录下的Screenshots文件夹。

4. Python中的继承的使用

本文开始介绍一个面向对象设计领域里,很常见的一种思想,继承。继承有很多好处,常听到的一句话就是,子类能够直接使用父类的方法,这样就可以减少子类代码量。其实,在自动化测试框架设计过程中,是很有必要把继承加入到你的测试脚本中去。接下来我们,简单写一个Python文件,来演示下继承的基本使用。

4.1 新建classA.py

1. 在test1包名下新建一个classA.py,这个就是我们的父类,里面有一个打开chrome浏览器和打开百度首页的方法。

4.1.2 代码实现:
4.1.3 参考代码:
# coding=utf-8?

# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行

# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2019-12-16
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之4-python+ selenium自动化测试 - python基础扫盲
'''

# 3.导入模块

from selenium import webdriver
import time


class ClassA(object):

    def open_baidu(self):
        driver = webdriver.Chrome()
        driver.maximize_window()
        driver.get("https://www.baidu.com")
        time.sleep(1)
        driver.quit()

4.2 新建classB.py

1. 在test2包下新建一个classB.py文件,这个继承classA.py里的ClassA类。

4.2.1 代码实现:
4.2.2 参考代码:
# coding=utf-8?

# 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行

# 2.注释:包括记录创建时间,创建人,项目名称。
'''
Created on 2019-12-16
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之4-python+ selenium自动化测试 - python基础扫盲
'''

# 3.导入模块

from test1.classA import ClassA


class ClassB(ClassA):

    def test_inherit(self):
        self.open_baidu()

test = ClassB()
test.test_inherit()
4.2.3 运行结果:

运行代码后,控制台打印如下图的结果

通过上面可以看出,只需要一句代码就可以实现ClassA中的方法,这个就是继承的好处,减少了很多代码的书写,提高代码的复用。在定义ClassB的时候就要指明ClassB的父类是ClassA. 继承相关的话题就介绍到这里,将在后面自动化框架设计会再次提到。

5. 小结

5.1 中文乱码

遇到的问题:细心地小伙伴或者同学们会发现在日志文件中的内容或出现中文乱码,如下图示:

解决办法:在FileHandler 此处要设置 encoding 格式,

fh = logging.FileHandler(log_name,encoding='utf-8')

修改后,运行代码日志文件内容如下图所示:

5.2 路径问题

因为宏哥在代码实践的过程中这部分遇到小问题,就是日志文件和截图放不在指定的文件夹下,所以这里拿出来单独说一下。

        # 创建一个handler,用于写入日志文件
        rq = time.strftime('%Y%m%d%H%M', time.localtime(time.time()))
        #当前目录
        print(os.getcwd())
        #根目录
        print(os.path.dirname(os.getcwd()))
        #log_path = (os.path.dirname(os.getcwd())+ '\\Logs\\')
        log_path = os.getcwd() + '\\Logs\\'
        print(log_path)

代码说明:

os.getcwd() :获取的当前最外层调用的脚本路径,即getPath所在的目录也可描述为起始的执行目录,A调用B,起始的是A,那么获取的就是A所在的目录路径。

os.path.dirname():去掉脚本的文件名,返回目录。

好了,今天的分享就到这里吧!!!谢谢各位的耐心阅读。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Appium+python自动化(四十)-Appium自动化测试框架综合实践 - 代码实现(超详解)

    今天我们紧接着上一篇继续分享Appium自动化测试框架综合实践 - 代码实现。由于时间的关系,宏哥这里用代码给小伙伴演示两个模块:注册和登录。

    北京-宏哥
  • Appium+python自动化(三十二)- 代码写死一时爽,框架重构火葬场 - PageObject+unittest(超详解)

    江湖有言:”代码写死一时爽,框架重构火葬场“,更有人戏言:”代码动态一时爽,一直动态一直爽?“,虽然听起来有点耸人听闻,但也没有想象中的那么严重,我们在开发写代...

    北京-宏哥
  • python接口自动化(四十二)- 项目结构设计之大结局(超详解)

      这一篇主要是将前边的所有知识做一个整合,把各种各样的砖块---模块(post请求,get请求,logging,参数关联,接口封装等等)垒起来,搭建一个房子。...

    北京-宏哥
  • 一个不小心,就把公司JS代码变成了圣诞树,CTO让我滚回家~

    2、把js代码分割成一小块,尽量小。然后用逐行填充的方式,分别替换到上一步生成的字符画里去

    疯狂的技术宅
  • Python如何操作MySQL

    mysql的安装图解https://jingyan.baidu.com/art... navicat for mysql破解可以看下这个文章https://ww...

    用户2398817
  • Pyqt5自定义控件--带全选功能的复选框

    用户6021899
  • 小程序的登录与静默续期

    每一个有数据交互的小程序,都会涉及到登录、token 等问题,openid 又是什么呢?怎么使用静默续期,来提升用户体验呢?

    ITer.996
  • 以太坊源码机制:挖矿

    狗年吉祥,开工利是,我们继续研究以太坊源码。从本篇文章开始,我们会深入到以太坊核心源码中去,进而分析与研究以太坊的核心技术。 关键字:拜占庭,挖矿,矿工...

    文彬
  • 每周学点大数据 | No.45 基于路径的图算法

    No.45期 基于路径的图算法 Mr. 王:接下来我们看一类具体的问题,这类问题叫作基于路径的图算法。这类算法的目标是计算节点间关于路径的信息。在这类问题中,图...

    灯塔大数据
  • python bottle 简介

    bottle 是一个轻量级的python web框架, 可以适配各种web服务器,包括python自带的wsgiref(默认),gevent, cherryp...

    用户2398817

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动