自动化测试架构入门,python3、Selenium3、unittest

本文基于 python3 和 selenium3自动化测试框架,采用 Page Object 设计模式进行二次开发,通过对页面对象和测试代码进行分离,并封装了日志输出,浏览器引擎选择,二次封装常用方法。降低后期因页面变化带来的维护成本,减少了代码的重复,提高测试用例的可读性
注:这只是一个入门教程,关于selenium基础可以观看selenium教程,环境W10+pycharm

注:目录如下在这里插入图片描述

1. 创建包“framework"进行框架底层封装,可以根据自己的想法封装底层方法

1.1 创建文件logger.py: 对日志的输入进行封装,包括文件输出和控制台输出。

import logging
import os.path
import time
class Logger(object):
    def __init__(self,logger):
        # 创建一个logger
        self.logger=logging.getLogger(logger)
        self.logger.setLevel(logging.DEBUG)
        # 创建一个handler,用于写入日志文件

        rd=time.strftime('%Y%m%d%H%M%S',time.localtime(time.time()))
        log_path=os.path.dirname(os.path.abspath('.'))+'/logs/'
        log_name=log_path+rd+'.log'

        # 创建一个handler,用于写入日志文件
        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


注:需要在自行根目录下创建logs文件夹接收日志输出,否则会提示找不到文件夹。

1.2 创建文件browser_engine.py:通过读取配置文件去选择浏览器和url,并返回浏览器对象实例

import os.path
from configparser import ConfigParser
from selenium import webdriver
from framework.logger import Logger

logger=Logger("BrowserEngine").getlog()


class BrowserEngine(object):
    def open_browser(self):
        #读取配置文件
        config=ConfigParser()
        dir=os.path.dirname(os.path.abspath('.'))
        file_path=dir+'/config/config.ini'#此时需要在项目目录中创建config文件夹以及config.ini文件
        config.read(file_path)
        #读取配置文件属性
        browser=config.get("browserType","browserName")
        logger.info("You had select %s browser." % browser)
        url=config.get("testServer","URL")
        logger.info("The test server url is: %s" % url)

        if browser == "Firefox":
            self.driver=webdriver.Firefox()
            logger.info("Starting firefox browser.")
        elif browser == "Chrome":
            self.driver=webdriver.Chrome(dir+'/tools/chromedriver.exe')#创建tools文件夹并放入驱动
            logger.info("Starting Chrome browser.")
        elif browser=="IE":
            self.driver=webdriver.Ie(dir+'/tools/IEDriverServer.exe')
            logger.info("Starting IE browser.")
        self.driver.get(url)
        logger.info("Open url: %s" % url)
        self.driver.maximize_window()
        logger.info("Maximize the current window.")
        self.driver.implicitly_wait(10)
        logger.info("Set implicitly wait 10 seconds.")
        return self.driver
    def quit_browser(self):
        logger.info("Now, Close and quit the browser.")
        self.driver.quit()

注:此时需要新建两个文件夹,config用来存储配置文件,tools用来放入浏览器驱动

1.3创建文件base_page.py:封装了selenium库中常用的方法,包括对象查找,截图输出,浏览器的前进后退,清除和输入

import time
from framework.logger import Logger
import os.path
from selenium.common.exceptions import NoSuchElementException
logger=Logger('BasePage').getlog()
#定义一个页面基类,让所有页面继承这个类

class BasePage(object):
    def __int__(self,driver):
        self.driver=driver
    def quit_browser(self):
        self.driver.quit()
        logger.info("browser is quit")
    def forword(self):
        self.driver.forword()
        logger.info("Click forward on current page.")
    def back(self):
        self.driver.back()
        logger.info("Click back on current page.")
    def wait(self,seconds):
        self.driver.implicitly_wait(seconds)
        logger.info("wait for %d seconds." % seconds)

    def close(self):
        try:
            self.driver.close()
            logger.info("Closing and quit the browser.")
        except NameError as e:
            logger.error("Failed to quit the browser with %s" % e)
    #截屏
    def get_windows_imgs(self):
        file_path=os.path.dirname(os.path.abspath('.'))+'/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)
            logger.info("Had take screenshot and save to folder : /screenshots")
        except NameError as e:
            logger.error("Failed to take screenshot! %s" % e)
            self.driver.get_windows_img()
    #寻找元素方法
    def find_element(self,*selector):#传入可变参数实现对元组的拆分
        try:
            element=self.driver.find_element(*selector)
            logger.info("The element looked up is %s "% (selector[1]))
            return element
        except NoSuchElementException as e:
            logger.error("NoSuchElementException: %s" % e)
            self.get_windows_img()
    #清除文本框
    def clear(self,*selector):
        el=self.find_element(*selector)
        try:
            el.clear()
            logger.info("Clear text in input box before typing.")
        except NameError as e:
            logger.error("Failed to clear in input box with %s" % e)
            self.get_windows_imgs()
    #输入
    def type(self,*selector,text):
        self.clear(*selector)
        el = self.find_element(*selector)
        try:
            el.send_keys(text)
            logger.info("Had type \' %s \' in inputBox" % text)
        except NameError as e:
            logger.error("Failed to type in input box with %s" % e)
            self.get_windows_imgs()

    def click(self, *selector):
        el = self.find_element(*selector)
        try:
            el.click()
            logger.info("The element \' %s \' was clicked." % el.text)
        except NameError as e:
            logger.error("Failed to click the element with %s" % e)

    #获得网页标题
    def get_page_title(self):
        logger.info("Current page title is %s" % self.driver.title)
        return self.driver.title

    @staticmethod
    def sleep(seconds):
        time.sleep(seconds)
        logger.info("Sleep for %d seconds" % seconds)

注:创建screenshots文件夹以接收截图文件

2创建包“pageobjects"进行页面封装

2.1创建文件“baidu_homepage.py":进行百度首页封装

from framework.base_page import BasePage
from selenium.webdriver.common.by import By
class homepage(BasePage):
    input_box=(By.ID,'kw')
    search_submit_btn=(By.XPATH,'//*[@id="su"]')
    news_link=(By.XPATH,'//*[@id="url"]/a[@name="tj_trnews"]')

    def type_search(self,text):
        self.type(*self.input_box,text=text)#text为命名关键字参数必须传入参数名

    def send_submit_btn(self):
        self.click(*self.search_submit_btn)

    def click_news(self):
        self.click(*self.news_link)

2.2 创建文件”baidu_news_home":进入新闻界面

# coding=utf-8
from framework.base_page import BasePage


class NewsHomePage(BasePage):
    # 点击体育新闻入口
    sports_link = "xpath=>//*[@id='channel-all']/div/ul/li[5]/a"

    def click_sports(self):
        self.click(self.sports_link)
        self.sleep(2)

3创建包“testsuites”:进行测试用理编写和封装

3.1 创建文件“test_baidu_search.py"进行测试用例编写

import time
import unittest
from framework.browser_engine import BrowserEngine
from pageobjects.baidu_homepage import HomePage
class BaiduSearch(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.browse=BrowserEngine()
        cls.driver=cls.browse.open_browser()
    @classmethod
    def tearDownClass(cls):
        cls.browse.quit_browser()
    def test_baidu_search(self):
        """
                这里一定要test开头,把测试逻辑代码封装到一个test开头的方法里。
                :return:
         """
        homepage=HomePage(self.driver)
        homepage.type_search("苍井空")
        homepage.send_submit_btn()
        time.sleep(2)
        homepage.get_windows_imgs()
        try:
            assert "苍井空" in self.driver.title
            print("Test Pass")
        except Exception as e:
            print('Test Fail.',e)

    def test_search2(self):
        homepage = HomePage(self.driver)
        homepage.type_search('python')  # 调用页面对象中的方法
        homepage.send_submit_btn()  # 调用页面对象类中的点击搜索按钮方法
        time.sleep(2)
        homepage.get_windows_imgs()  # 调用基类截图方法
        print('Test Pass.')

    def test_get_title(self):
        homepage = HomePage(self.driver)
        print(homepage.get_page_title())

if __name__ == '__main__':
    unittest.main()

注:(setUp():每个测试case运行之前运行,tearDown():每个测试case运行完之后执行setUpClass():必须使用@classmethod 装饰器, 所有case运行之前只运行一次,tearDownClass():必须使用@classmethod装饰器, 所有case运行完之后只运行一次现在已经可以运行测试用例了)这里用pycharm直接运行会可能出现一些问题,我专门写了一篇文章记录,在我主页里

创建文件”test_baidu_news.py“:

# coding=utf-8
import time
import unittest
from framework.browser_engine import BrowserEngine
from pageobjects.baidu_news_home import NewsHomePage
class BaiduSearch(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        """
        测试固件的setUp()的代码,主要是测试的前提准备工作
        :return:
        """
        browse = BrowserEngine()
        cls.driver = browse.open_browser()

    @classmethod
    def tearDownClass(cls):
        """
        测试结束后的操作,这里基本上都是关闭浏览器
        :return:
        """
        cls.driver.quit()

    def test_baidu_news(self):
        newspage = NewsHomePage(self.driver)
        newspage.click_sports()
        time.sleep(2)
        newspage.get_windows_imgs()  # 调用基类截图方法
        print('Test Pass.')


if __name__ == '__main__':
    unittest.main()

3.3创建网页版测试报告,需要先下载HTMLTestRunnerCN到当前文件夹中,直接用轮子即可。创建文件”TestRunner.py":

import unittest
from MyHTMLTestReportCN import HTMLTestRunner
import os
import time
import sys
sys.path.append("..")
# 定义输出的文件位置和名字
report_path = os.path.dirname(os.path.abspath('.')) + '/test_report/'

now = time.strftime("%Y-%m-%d-%H_%M_%S", time.localtime(time.time()))

HtmlFile = report_path+now+"HTMLtemplate.html"

fp = open(HtmlFile, "wb")


if __name__=='__main__':
    suite = unittest.TestLoader().discover("testsuites")
    runner = HTMLTestRunner(stream=fp, title='测试报告', description='执行情况',tester='XKS')
    runner.run(suite)

注:需要新建文件夹test_report接收HTML报告

4结果如下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值