Web自动化(二)
unittest单元测试框架
setUp()和tearDown()方法可以在测试运行前后做一些操作,每次执行一条用例都会调用setUp和tearDown方法
常用断言方法
1、assertEqual(a,b,[msg='']):断言a和b是否相等,相等时用例通过,msg为当测试用例不通过时的返回信息
2、assertNotEqual(a,b,[msg='']):断言a和b是否相等,不相等时用例通过,msg为当测试用例不通过时的返回信息
3、assertTrue(x,[msg='']):断言x是否为True,是True则测试用例通过
4、assertFalse(x,[msg='']):断言x是否为False,是False则测试用例通过
5、assertIs(a,b,[msg='']):断言a是否是b,是则测试用例通过
6、assertNotIs(a,b,[msg='']):断言a是否是b,不是则测试用例通过
7、assertIsNone(x,[msg='']):断言x是否为None,是则测试用例通过
8、assertIsNotNone(x,[msg='']):断言x是否为None,不是则测试用例通过
9、assertIn(a,b,[msg='']):断言a是否在b中,是则测试用例通过
10、assertNotIn(a,b,[msg='']):断言a是否在b中,不是则测试用例通过
11、assertIsInstance(a,b,[msg='']):断言a是否为b的一个实例,是则用例通过
import unittest from selenium import webdriver class testCase(unittest.TestCase): def setUp(self): self.dr = webdriver.Chrome() def test_QQlogin(self): self.dr.get('https://mail.qq.com') self.assertEqual(self.dr.title, '登录QQ邮箱', '页面跳转失败') print('第一条用例') def test_MaoyanMovie(self): self.dr.get('http://maoyan.com/') self.assertEqual(self.dr.title, '电影院票房购票_评分_选座_经典影视推荐-猫眼电影', '页面跳转失败') print('第二条用例') def tearDown(self): self.dr.quit() if __name__ == '__main__': unittest.main()
引入setUpClass()和tearDownClass()测试固件,可保证执行用例前和执行完所有用例后的操作
import unittest from selenium import webdriver class testCase(unittest.TestCase): @classmethod def setUpClass(cls): cls.dr = webdriver.Chrome() def test_QQlogin(self): self.dr.get('https://mail.qq.com') self.assertEqual(self.dr.title, '登录QQ邮箱', '页面跳转失败') print('第一条用例') def test_MaoyanMovie(self): self.dr.get('http://maoyan.com/') self.assertEqual(self.dr.title, '电影院票房购票_评分_选座_经典影视推荐-猫眼电影', '页面跳转失败') print('第二条用例') @classmethod def tearDownClass(cls): cls.dr.quit() if __name__ == '__main__': unittest.main()
生成HTML测试报告
将HTMLTestRunner.py复制到Python安装目录的Lib下
编写allTest.py文件,运行所有测试脚本
目录结构如下:
...\TestCases:存放测试用例\
...\TestCases\__init__:声明TestCases包文件
...\TestCases\testUnit.py:自动化测试用例
...\TestCases\Myunit.py:存放测试固件
...\Reports:存放HTML测试报告
...\allTest.py:运行所有测试用例主程序文件
import os, time, unittest from HTMLTestRunner import HTMLTestRunner def getAllCases(): #获取TestCases下的所有测试模块 Testsuite = unittest.defaultTestLoader.discover(start_dir=os.path.join(os.path.dirname(__file__),'TestCases'),pattern='test*.py') return Testsuite def RunMain(): #生成测试报告,写入指定Reports目录 fp = open(os.path.join(os.path.dirname(__file__),'Reports',time.strftime('%Y-%m-%d-%H-%M-%S')+'report.html'),'wb') HTMLTestRunner(stream=fp,title='测试报告',description='使用unittest完成').run(getAllCases()) if __name__ == '__main__': RunMain() '''discover()函数用于读取TestCases目录下的以test开头的.py文件,并返回所有测试模块下的测试用例'''
数据驱动测试
需在测试类上使用@ddt.ddt装饰器,在测试用例上使用@ddt.data装饰器,@ddt.data可以把参数作为测试数据,可以是单个值,或字典、列表、元组。对于列表和元组,需要使用@ddt.unpack装饰器把列表或者元组解析成多个参数
单个参数示例
import ddt import unittest Data = [ {'name': 'keep learning'}, {'age': 18}, {'address': '上海地区'} ] @ddt.ddt class TestModules(unittest.TestCase): @classmethod def setUp(self): print('begin') @classmethod def tearDown(self): print('over') @ddt.data(*Data) def test_DataDriver(self,Data): print('DDT数据驱动',Data) if __name__ == '__main__': unittest.main()
列表或者元组示例
import ddt import unittest Data = [ ['admin', 'admin', '登录失败'], ['admin','admin123','登录成功'], ['','','登录失败'] ] @ddt.ddt class TestModules(unittest.TestCase): def setUp(self): print('testcase begining') def tearDown(self): print('testCase over') @ddt.data(*Data) @ddt.unpack def test_DataDriver(self,user,pwd,msg): print('DDT数据驱动', user) print('DDT数据驱动', pwd) print('DDT数据驱动', msg) if __name__ == '__main__': if __name__ == '__main__': unittest.main()
Excel读取测试数据并执行用例示例
import unittest, xlrd, ddt from time import sleep from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def readUserName(row): book = xlrd.open_workbook('测试数据.xlsx', 'r') table = book.sheet_by_index(0) return table.row_values(row)[0] def readPasswd(row): book = xlrd.open_workbook('测试数据.xlsx', 'r') table = book.sheet_by_index(0) return table.row_values(row)[1] def readMsg(row): book = xlrd.open_workbook('测试数据.xlsx', 'r') table = book.sheet_by_index(0) return table.row_values(row)[2] class TestSouHuLogin(unittest.TestCase): def setUp(self): self.dr = webdriver.Chrome() self.dr.maximize_window() self.test_url = 'http://mail.sohu.com/fe/#/login' def tearDown(self): self.dr.quit() def by_css(self, usernameloc): # 重写css定位 return self.dr.find_element_by_css_selector(usernameloc) def getassertText(self): try: sleep(2) loctor = (By.CSS_SELECTOR, '.topHolder.ng-binding') WebDriverWait(self.dr, 5, 0.5).until(EC.presence_of_element_located(loctor)) return self.by_css('.topHolder.ng-binding').text except Exception as e: print('元素定位失败,报错原因{}'.format(e)) def souhuLogin(self, user, passwd): #封装登录操作 self.by_css('.addFocus.ipt-account.ng-pristine.ng-valid').send_keys(user) self.by_css('.addFocus.ng-pristine.ng-valid').send_keys(passwd) self.by_css('.btn-login.fontFamily').click() def test_souHuLogin_001(self): self.dr.get(self.test_url) sleep(3) self.souhuLogin(readUserName(0),readPasswd(0)) self.assertEqual(self.getassertText(),readMsg(0),msg='错误') def test_souHuLogin_002(self): self.dr.get(self.test_url) sleep(3) self.souhuLogin(readUserName(1),readPasswd(1)) self.assertEqual(self.getassertText(),readMsg(1),msg='错误') def test_souHuLogin_003(self): self.dr.get(self.test_url) sleep(3) self.souhuLogin(readUserName(2),readPasswd(2)) self.assertEqual(self.getassertText(),readMsg(2),msg='错误') if __name__ == '__main__': unittest.main()
Excel整合成一个列表
import xlrd def readData(): book = xlrd.open_workbook('测试数据.xlsx','r') table = book.sheet_by_index(0) newRows = [] for rowValue in range(1,table.nrows): #行数进行迭代 newRows.append(table.row_values(rowValue,0,table.ncols)) return newRows
使用yaml读取并执行用例
import yaml import unittest, ddt from time import sleep from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC def readyaml(): f = open('data.yaml', 'r', encoding='utf-8') data = yaml.load(f.read()) f.close() return data class TestSouHuLogin(unittest.TestCase): def setUp(self): self.dr = webdriver.Chrome() self.dr.maximize_window() self.test_url = 'http://mail.sohu.com/fe/#/login' def tearDown(self): self.dr.quit() def by_css(self, usernameloc): # 重写css定位 return self.dr.find_element_by_css_selector(usernameloc) def getassertText(self): try: sleep(2) loctor = (By.CSS_SELECTOR, '.tipHolder.ng-binding') WebDriverWait(self.dr, 5, 0.5).until(EC.presence_of_element_located((loctor))) return self.by_css('.tipHolder.ng-binding').text except Exception as e: print('元素定位失败,报错原因{}'.format(e)) def souhuLogin(self, user, passwd): # 封装登录操作 self.by_css('.addFocus.ipt-account.ng-pristine.ng-valid').send_keys(user) self.by_css('.addFocus.ng-pristine.ng-valid').send_keys(passwd) self.by_css('.btn-login.fontFamily').click() def test_souHuLogin_001(self): self.dr.get(self.test_url) sleep(3) self.souhuLogin(readyaml()['userNull']['username'], readyaml()['userNull']['password']) self.assertEqual(self.getassertText(), readyaml()['userNull']['assertText'], msg='错误') # def test_souHuLogin_002(self): # self.dr.get(self.test_url) # sleep(3) # self.souhuLogin(readUserName(1),readPasswd(1)) # self.assertEqual(self.getassertText(),readMsg(1),msg='错误') # def test_souHuLogin_003(self): # self.dr.get(self.test_url) # sleep(3) # self.souhuLogin(readUserName(2),readPasswd(2)) # self.assertEqual(self.getassertText(),readMsg(2),msg='错误') if __name__ == '__main__': unittest.main()
parameterized参数化
import unittest from selenium import webdriver from time import sleep from parameterized import parameterized class LoginTest(unittest.TestCase): def setUp(self): self.dr = webdriver.Chrome() self.dr.maximize_window() self.test_url = 'http://mail.sohu.com/fe/#/login' def tearDown(self): self.dr.quit() def by_css(self, usernameloc): # 重写css定位 return self.dr.find_element_by_css_selector(usernameloc) def getassertText(self): try: return self.by_css('.tipHolder.ng-binding').text except Exception as e: print('元素定位失败,报错原因{}'.format(e)) def souhuLogin(self, user, passwd): # 封装登录操作 self.by_css('.addFocus.ipt-account.ng-pristine.ng-valid').send_keys(user) self.by_css('.addFocus.ng-pristine.ng-valid').send_keys(passwd) self.by_css('.btn-login.fontFamily').click() @parameterized.expand([ ('', '', '请输入账号密码'), ('admin111@sohu.com'), ('', 'a123456789', '请输入账号密码')]) def test_login(self,username,password,assert_text): self.dr.get(self.test_url) sleep(3) self.souhuLogin(username,password) self.assertEqual(self.getassertText(),assert_text) if __name__ == '__main__': unittest.main(verbosity=2)
发送邮件
第一个示例,无附件
import smtplib #调用SMTP发件服务 from email.mime.text import MIMEText #导入做纯文本的邮件模板类 smtpsever = 'smtp.qq.com' sender = '840633025@qq.com' psw = 'fgwgbeghglxybbei' receiver = '313891664@qq.com' port = 465 body = '这是第一封测试邮件' #邮件内容 msg = MIMEText(body,'html','utf-8') msg['from'] = '840633025@qq.com' msg['to'] = '313891664@qq.com' msg['subject'] = '这是纯文本发送的邮件示例' #邮件名称 smtp = smtplib.SMTP_SSL(smtpsever,port) #调用发件服务 smtp.login(sender,psw) #通过发送者邮箱账号和授权码登录邮箱 smtp.sendmail(sender,receiver,msg.as_string()) #发送邮件,信息以字符串方式保存 smtp.quit()
带附件的邮件发送
import smtplib #调用SMTP发件服务 from email.mime.text import MIMEText #导入做纯文本的邮件模板类 from email.mime.multipart import MIMEMultipart smtpsever = 'smtp.qq.com' sender = '840633025@qq.com' psw = 'fgwgbeghglxybbei' receiver = '313891664@qq.com' port = 465 filepath = r"./sql.txt" with open(filepath,'rb') as fp: mail_body = fp.read() msg = MIMEMultipart() msg['from'] = '840633025@qq.com' msg['to'] = '313891664@qq.com' msg['subject'] = '这是带附件的邮件' body = MIMEText(mail_body,'html','utf-8') msg.attach(body) att = MIMEText(mail_body,'base64','utf-8') att['Content-Type'] = 'application/octet-stream' att['Content-Disposition'] = 'attachment;filename="test_report.html"' msg.attach(att) try: smtp = smtplib.SMTP_SSL() smtp.connect(smtpsever) smtp.login(sender,psw) except: smtp = smtplib.SMTP_SSL(smtpsever,port) smtp.login(sender, psw) smtp.sendmail(sender,receiver,msg.as_string()) smtp.quit()
自动化测试封装
浙公网安备 33010602011771号