selenium自动化简易测试框架总结

一、目录结构

Base目录:公共、基础的方法和类

logs:日志文件

PageObject:每个页面元素的定位、操作方法封装

report:测试报告

UniTest:测试用例编写以及执行

二、各部分的示例代码

Base/base_page.py:所有页面都需要用到的方法

from
selenium import webdriver import time import os #定义所有页面都需要的基础类 class BasePage(): #初始化操作,获取浏览器驱动、地址 def __init__(self,driver,url): self.driver = driver self.url = url #打开浏览器,访问页面 def open(self): self.driver.get(self.url) self.driver.maximize_window() #定位页面元素 def locator_element(self,*locator): el = self.driver.find_element(*locator) return el #退出浏览器 def quit(self): self.driver.quit() #定义截图函数 def insert_images(self,file_name): base_dir = os.path.dirname(os.path.dirname(__file__)) file_path = os.path.join(base_dir + '/','report/images/') self.driver.get_screenshot_as_file(file_path+file_name) #获取用例执行时时间 def get_current_time(self): return time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime()) if __name__ == '__main__': path = os.path.dirname(os.path.dirname(__file__)) file_path = os.path.join(path + '/','report/images/','test.html') print(path) print(file_path)

log.py:日志操作方法

import logging
import os
import time


class OptionLog():
    def __init__(self):
        #创建logger实例
        self.logger = logging.getLogger()
        #设置logger输出级别
        self.logger.setLevel(logging.INFO)
        #设置日志输出格式
        formatter = logging.Formatter('%(asctime)s-%(module)s-%(funcName)s:%(message)s')

        #按照日期创建日志文件
        base_dir = os.path.dirname(os.path.dirname(__file__)) + '/'
        file_path = os.path.join(base_dir,'logs')
        current_data = time.strftime('%Y-%m-%d',time.localtime())
        file_name = file_path + '/' + current_data + '.log'

        #日志保存到文件
        self.file_handler = logging.FileHandler(file_name,'a',encoding='utf-8')
        self.file_handler.setFormatter(formatter)

        #日志输出到控制台
        self.consele_handler = logging.StreamHandler()
        self.consele_handler.formatter = formatter

        #为logger添加日志处理器
        self.logger.addHandler(self.file_handler)
        self.logger.addHandler(self.consele_handler)

    def get_logger(self):
        return self.logger

    def close_handle(self):
        #移除日志句柄
        self.logger.removeHandler(self.file_handler)
        self.logger.removeHandler(self.consele_handler)
        #关闭日志处理器
        self.file_handler.close()
        self.consele_handler.close()


if __name__ == '__main__':
    myLog = OptionLog()
    logger = myLog.get_logger()
    print(logger)
    logger.info('测试日志输出')
    myLog.close_handle()

send_email.py:发送邮件方法封装

import os
import time
import smtplib
from email.utils import formataddr
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.header import Header

from Base import BASE_DIR
from Base.log import OptionLog

class SendEmail():
    def __init__(self,sender,pwd,recevier,content='这是测试报告,请领导查阅',subject='selenium测试报告'):
        self.sender = sender #发件人邮箱账号
        self.pwd = pwd #发件人邮箱密码
        self.receiver = recevier #接收者
        self.content = content #发送的邮件内容
        self.subject = subject #邮件主题

    def send(self):
        """"
        发送最新测试报告
        """
        #找出最新的测试报告
        file_path = os.path.join(BASE_DIR ,'report\html\')
        last_file = self.find_latest_file(file_path)
        last_file_name = os.path.basename(last_file)

        #实例化日志对象
        logger = OptionLog().get_logger()

        #组织邮件附件
        try:
            sendfile = open(last_file, 'r', encoding='utf-8').read()
            msg = MIMEText(sendfile, 'base64', 'utf-8')
            msg['Content-Type'] = 'application/octet-sream'
            msg['Content-Disposition'] = "attachment;filename =%s "%last_file_name
            msg['Subject'] = 'selenium测试报告'
            msg['TO'] = ','.join(self.receiver) #当接收者是多人的时候,需要传字符串,否则会报错

            #组织邮件正文信息
            msgRoot = MIMEMultipart('related')
            msgRoot['Subject'] = self.subject
            content = MIMEText(self.content.encode(),'plain', 'utf-8')

            #添加正文、附件
            msgRoot.attach(msg)
            msgRoot.attach(content)

            #登录qq邮件服务器发送邮件
            s = smtplib.SMTP_SSL('smtp.qq.com', 465)
            s.login(self.sender, self.pwd)
            s.sendmail(self.sender, self.receiver, msgRoot.as_string())

            #记录成功日志
            logger.info('测试报告发送成功')

        except Exception as e:
            logger.info(str(e))

    #找出目录下最新创建的文件
    def find_latest_file(self,file_path):
        files = os.listdir(file_path)
        files.sort(key=lambda file:os.stat(file_path+file).st_ctime )
        latest_file = files[-1]
        latest_file_path = os.path.join(file_path,latest_file)
        return latest_file_path


if __name__ == '__main__':
    email_obj = SendEmail('xxxxx@qq.com','xxxxxxxxx',['xxxxxxxx@qq.com','xxxxxxxx@qq.com'])
    res = email_obj.send()

login_page.py:登录页面对象封装

from Base.base_page import BasePage
from selenium.webdriver.common.by import By
from selenium import webdriver


class LoginPage(BasePage):
    accout_id = (By.ID,'userAccount')
    password_id = (By.ID,'password')
    login_xpath = (By.CLASS_NAME,'ant-btn')

    #输入用户名
    def input_account(self,account):
        self.locator_element(*self.accout_id).send_keys(account)

    #输入密码
    def input_password(self,pwd):
        self.locator_element(*self.password_id).send_keys(pwd)

    #点击登录
    def click_login_ele(self):
        self.locator_element(*self.login_xpath).click()

    user_empty_hit = (By.XPATH,'//*[@id="root"]/div/div/div[2]/form/div[1]/div/div[2]/div')
    pwd_empty_hit = (By.XPATH,'//*[@id="root"]/div/div/div[2]/form/div[2]/div/div[2]/div')
    user_pwd_error_hit = (By.XPATH,'/html/body/div[2]/div/span/div/div/div/span[2]')
    #用户名或密码错误提示
    def user_pwd_error_msg(self):
        return self.locator_element(*self.user_pwd_error_hit).text

    #用户名为空提示
    def user_empty_msg(self):
        return self.locator_element(*self.user_empty_hit).text

    #密码为空提示
    def pwd_empty_msg(self):
        return self.locator_element(*self.pwd_empty_hit).text

    #登录流程
    def login(self,account,pwd):
        self.open()
        self.input_account(account)
        self.input_password(pwd)
        self.click_login_ele()

if __name__ == '__main__':
    driver = webdriver.Chrome()
    url = 'http://xxxxxx.com/login'
    login_page = LoginPage(driver,url)
    login_page.login('22222','333333')
    import time
    time.sleep(3)
    login_page.user_pwd_error_msg()

test_case.py:测试用例封装

import time
import unittest
from ddt import data,ddt,unpack
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

from PageObject.login_page import LoginPage
from Base.log import OptionLog


@ddt
class TestLogin(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.log = OptionLog()
        cls.logger = cls.log.get_logger()

    @classmethod
    def tearDownClass(cls):
        cls.log.close_handle()
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(10)

    def tearDown(self):
        time.sleep(5)
        self.driver.quit()

    @data(('http://xxxxxx.com/login','xxxxxxxx','123456'))
    @unpack
    def test_login1(self,url,account,pwd):
        """用户名、密码正确"""
        self.logger.info('用户名、密码正确')
        login_page = LoginPage(self.driver,url)
        login_page.login(account,pwd)
        title = self.driver.title
        time.sleep(5)
        #判断登录后页面标题
        page_title = EC.title_contains("地图慧")(self.driver)
        #判断页面左下角登录账号昵称
        user_name = EC.presence_of_element_located((By.XPATH,'//*[@id="superNav"]/div/footer/div[2]/span[2]'))(self.driver)
        user_name1 = EC.visibility_of_element_located((By.XPATH,'//*[@id="superNav"]/div/footer/div[2]/span[2]'))(self.driver)
        self.assertEqual(True,page_title)
        self.assertNotEqual(False,user_name1)

        #用例执行完后截图
        login_page.insert_images(login_page.get_current_time() + '(用户名、密码正确).png')


    @data(('http://xxxxxxx.com/login', 'xxxxxxxx', '111111'))
    @unpack
    def test_login2(self,url,account,pwd):
        """用户名、密码错误"""
        self.logger.info('用户名、密码错误')
        login_page = LoginPage(self.driver,url)
        login_page.login(account,pwd)
        time.sleep(3)
        self.assertEqual(login_page.user_pwd_error_msg(),'账号或密码错误!')

        # 用例执行完后截图
        login_page.insert_images(login_page.get_current_time() + '(用户名、密码错误).png')

    @data((('http://xxxxxxx.com/login', '', '111111')))
    @unpack
    def test_login3(self,url,account,pwd):
        """用户名为空,密码正确"""
        self.logger.info('用户名为空,密码正确"')
        login_page = LoginPage(self.driver, url)
        login_page.login(account, pwd)
        time.sleep(3)
        self.assertEqual(login_page.user_empty_msg(), '请输入手机号')

        # 用例执行完后截图
        login_page.insert_images(login_page.get_current_time() + '(用户名为空,密码正确).png')

    @data((('http://xxxxxxx.com/login', 'xxxxxxxx', '')))
    @unpack
    def test_login4(self,url,account,pwd):
        """用户名正确,密码为空"""
        self.logger.info('用户名正确,密码为空')
        login_page = LoginPage(self.driver, url)
        login_page.login(account, pwd)
        time.sleep(3)
        self.assertEqual(login_page.pwd_empty_msg(), '密码不能为空')

        # 用例执行完后截图
        login_page.insert_images(login_page.get_current_time() + '(用户名正确,密码为空).png')

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

run_case.py:测试用例的执行

import os
import time

import unittest
from HTMLTestRunner import HTMLTestRunner

from Base import BASE_DIR
from Base.send_email import SendEmail

def run_all_case():
    #查找指定目录下的用例文件
    discover = unittest.defaultTestLoader.discover('./','test_*.py',top_level_dir=None)
    # runner = unittest.TextTestRunner()

    #按照用例执行时间命名生成测试报告
    current_time  = time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime())
    report_path = os.path.join(BASE_DIR+'/report/html/'+ current_time + 'result.html')

    with open(report_path,'wb') as fp:
        runner = HTMLTestRunner(stream=fp)
        runner.run(discover)

    #用例执行完后发送测试报告
    email_obj = SendEmail('xxxxxx@qq.com', 'xxxxxxx', ['xxxxxxx@qq.com', 'xxxxxxxxx@qq.com'])
    email_obj.send()

if __name__ == '__main__':
    run_all_case()

 

原文地址:https://www.cnblogs.com/canghai1024/p/13261367.html