一、目录结构
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()