Selenium+Python ---- 免登录、等待、unittest单元测试框架、PO模型
转载 https://www.cnblogs.com/ailiailan/p/8082023.html
1、免登录
在进行测试的过程中难免会遇到登录的情况,给测试工作添加了工作量,本文仅提供一些思路供参考
解决方式:手动请求中添加cookies、火狐的profile文件记录信息实现、人工介入、万能验证码、去掉验证码
1.1、手动在请求中添加cookies信息
1 url = "http://www.baidu.com"
2 driver = webdriver.Firefox()
3 driver.get(url)
4 time.sleep(3)
5 #添加cookies的方式
6
7 c1 = {'domain': '.baidu.com',
8 'name':'BDUSS',
9 'value': 'dyRlBucW9WOUhpNXducElPT1dlVHN1SFdFZUllTkJ-TEg5djNAAVe6gcaGFuc2hvdWthaQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHa68lh2uvJYU2',
10 'path': '/',
11 'httpOnly': True,
12 'secure':False
13 }
14 driver.add_cookie(c1)
15 time.sleep(3)
16 # print(driver.get_cookies()) #得到当前cookies信息
17 # driver.delete_all_cookies() #删除所有cookies信息
18 driver.refresh()
19 time.sleep(5)
20
21 driver.quit()
1.2、火狐的profile文件记录信息实现
1 #利用火狐profile文件的方式(前提:必须先手动登录一下)
2 profile_ff = "C:/Users/Hanxiaobei/AppData/Roaming/Mozilla/Firefox/Profiles/ytw908g4.default"
3
4 fp = webdriver.FirefoxProfile(profile_ff)
5 driver = webdriver.Firefox(fp)
6 url = "http://www.baidu.com"
7 driver.get(url)
8 time.sleep(5)
9 driver.quit()
1.3、人工介入
1 driver.find_element_by_link_text("登录").click()
2 driver.find_element_by_id("TANGRAM__PSP_8__userName").send_keys("hankai")
3 driver.find_element_by_id("TANGRAM__PSP_8__password").send_keys("hankai")
4 time.sleep(15) #导入等待时间人工输入验证码
5 driver.find_element_by_id("TANGRAM__PSP_8__submit").click()
6
7 time.sleep(5)
8 driver.quit()
1.4、万能验证码、去掉验证码
万能验证码、去掉验证码需要开发的配合
2、等待
2.1、time模块
1 import time
2
3 time.sleep(5)
2.2、隐式等待
1 driver.implicitly_wait(20)
2.3、显式等待
1 url = "http://www.baidu.com"
2 driver = webdriver.Firefox()
3 driver.get(url)
4 #显性等待
5 kk = WebDriverWait(driver,10).until(lambda driver:driver.find_element_by_id("kw"),message="worry!")
6 kk.send_keys("测试")
3、unittest单元测试框架
简单的unittest框架代码如下:
1 import unittest,time
2 from selenium import webdriver
3 from selenium.webdriver.common.by import By
4 class Baidu(unittest.TestCase):
5 def setUp(self):
6 self.driver = webdriver.Chrome()
7 url = "http://www.baidu.com"
8 self.driver.get(url)
9 self.driver.implicitly_wait(20)
10 self.verificationErrors = []
11
12 def tearDown(self):
13 self.driver.quit()
14 self.assertEqual([],self.verificationErrors,msg="验证失败")
15
16 def test_search(self):
17 self.driver.find_element(By.ID,"kw").send_keys("hanxiaobei")
18 self.driver.find_element(By.ID,"su").click()
19 time.sleep(5)
20
21 if __name__ == "__main__":
22 第一种形式:
23 #unittest.main()
24
25 第二种形式:
26 suite = unittest.TestSuite()
27 suite.addTest(Baidu("test_search"))
28
29 runner = unittest.TextTestRunner()
30 runner.run(suite)
可生成html报告的unittest框架代码如下:
1 from selenium import webdriver
2 import time
3 import unittest
4 import HTMLTestRunner
5
6 class Test_case(unittest.TestCase):
7 """测试类"""
8 def setUp(self):
9 self.url = "http://www.baidu.com"
10 self.driver = webdriver.Firefox()
11 self.driver.implicitly_wait(20)
12 self.verificationErrors = []
13
14 def tearDown(self):
15 self.driver.quit()
16 self.assertEqual([],self.verificationErrors)
17
18 def test_sou1(self):
19 """测试搜索演示1"""
20 self.driver.get(self.url)
21 self.driver.find_element_by_id("kw").send_keys("测试")
22 self.driver.find_element_by_id("su").click()
23 self.driver.close()
24 time.sleep(5)
25 def test_sou2(self):
26 """测试搜索演示2"""
27 self.driver.get(self.url)
28 self.driver.find_element_by_id("k").send_keys("自动化测试")
29 self.driver.find_element_by_id("su").click()
30 self.driver.close()
31 time.sleep(5)
32
33 #生成一个运行测试用例集合
34 suite = unittest.TestSuite()
35 suite.addTest(Test_case('test_sou1'))
36 suite.addTest(Test_case('test_sou2'))
37
38 '''
39 生成基于html的测试报告:
40 1定义一个文件的路径
41 2以写的方式进行打开文件
42 3调用htmltestrunner的方法生成测试报告
43 4运行测试集合
44 5关闭文件
45 '''
46 report_file=".\\20170423_report.html"
47 fp = open(report_file,"wb")
48 runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title="搜索",description="测试搜索结果")
49 runner.run(suite)
50 fp.close()
5、PO模型
PO就是一个设计思想,将代码以页面为单位进行组织,针对这个页面上的所有信息、相关操作都放到一个类中,从而使具体的测试用例变成了简单的调用和验证操作。
优点:进行了拆分和分层
缺点:对于复杂的业务page层变了,case也需要去改动
PO模型的目录结构:
其中,base_page是login_page、search_page的基础。test_login调用login_page,login_page调用base_page,同理test_search。
PO代码示例:
base_page.py
1 from selenium.webdriver.support.wait import WebDriverWait
2
3 '''
4 这个类主要是完成所有页面的一些公共方法的封装
5 '''
6 class Action(object):
7 #初始化
8 def __init__(self,se_driver):
9 self.driver = se_driver
10
11 #定义open方法
12 def open(self,url):
13 self.driver.get(url)
14 self.driver.maximize_window()
15
16 #重写元素定位的方法
17 def find_element(self,*loc):
18 try:
19 WebDriverWait(self.driver,20).until(lambda driver:driver.find_element(*loc).is_displayed())
20 return self.driver.find_element(*loc)
21 except Exception as e:
22 print("未找到%s"%(self,loc))
23
24 #定义script方法,用于执行js脚本
25 def script(self,src):
26 self.driver.execute_script(src)
27
28 #重写send_keys方法
29 def send_keys(self,loc,value,clear_first=True,clik_first=True):
30 try:
31 if clik_first:
32 self.find_element(*loc).click()
33 if clear_first:
34 self.find_element(*loc).clear()
35 self.find_element(*loc).send_keys(value)
36 except AttributeError:
37 print("未找到%s"%(self,loc))
login_page.py
1 from selenium.webdriver.common.by import By
2 from seleniumframework.PO import base_page
3 import time
4
5 class LoginPage(base_page.Action):
6 link_loc = (By.LINK_TEXT,"登录")
7 name_loc = (By.ID,"TANGRAM__PSP_8__userName")
8 password_loc = (By.ID,"TANGRAM__PSP_8__password")
9 submit_loc = (By.ID,"TANGRAM__PSP_8__submit")
10
11 username_top = (By.LINK_TEXT,"hanxiaobei")
12
13
14 def click_link(self):
15 self.find_element(*self.link_loc).click()
16 time.sleep(3) #等待3秒,等待登录弹窗加载完成
17
18 def run_case(self,value1,value2):
19 self.find_element(*self.name_loc).send_keys(value1)
20 self.find_element(*self.password_loc).send_keys(value2)
21 time.sleep(20) #手动输入验证码
22 self.find_element(*self.submit_loc).click()
23 time.sleep(5) #等待5秒,登录后的页面加载完成
24
25 def get_username(self):
26 return self.find_element(*self.username_top).text
test_login.py
1 import unittest
2 from selenium import webdriver
3 from seleniumframework.PO.login_page import LoginPage
4 import time
5
6 class TestBaiduLogin(unittest.TestCase):
7 """UI自动化登录"""
8 def setUp(self):
9 self.url = "http://www.baidu.com"
10 self.driver = webdriver.Firefox()
11 self.driver.implicitly_wait(20)
12 # self.verificationErrors = []
13
14 def tearDown(self):
15 time.sleep(5)
16 self.driver.quit()
17 # self.assertEqual([],self.verificationErrors)
18
19 def test_login(self):
20 """百度登录"""
21 sp = LoginPage(self.driver)
22 sp.open(self.url)
23 sp.click_link()
24 sp.run_case("hanxiaobei","xxxxxxx")
25 self.assertEqual(sp.get_username(),"hanxiaobei",msg="验证失败!")
main.py 运行的主入口
1 import unittest
2 import HTMLTestRunner
3
4 #相对路径
5 testcase_path = ".\\testcase"
6 report_path = ".\\report\\report.html"
7 def creat_suite():
8 uit = unittest.TestSuite()
9 discover = unittest.defaultTestLoader.discover(testcase_path,pattern="test_*.py")
10 for test_suite in discover:
11 # print(test_suite)
12 for test_case in test_suite:
13 uit.addTest(test_case)
14 return uit
15
16 suite = creat_suite()
17 fp = open(report_path,"wb")
18 runner = HTMLTestRunner.HTMLTestRunner(stream=fp,title="测试结果",description="测试搜索结果")
19 runner.run(suite)
20 fp.close()
解决报告命名的问题:
1 now = time.strftime("%Y-%m-%d-%H-%M-%S",time.localtime(time.time()))
2 print(now)
3 report_path = ".\\report\\"+now+"report.html"
测试报告截图:
search_page.py
1 from selenium.webdriver.common.by import By
2 from seleniumframework.PO import base_page
3
4 #继承base后既可以调用base的方法也可自己添加新的方法
5 class SearchPage(base_page.Action):
6
7 #通过id进行定位元素
8 search_loc = (By.ID,"kw")
9
10 def run_case(self,value):
11 #第一种利用原生的send_keys方法
12 self.find_element(*self.search_loc).send_keys(value)
13
14 #第二种利用二次封装的send_keys方法
15 # self.send_keys(self.search_loc,value)
test_search.py
1 import unittest
2 from selenium import webdriver
3 from seleniumframework.PO.search_page import SearchPage
4 import time
5
6 class TestBaiduSearch(unittest.TestCase):
7 """UI自动化搜索"""
8 def setUp(self):
9 self.url = "http://www.baidu.com"
10 self.driver = webdriver.Firefox()
11 self.driver.implicitly_wait(20)
12 self.verificationErrors = []
13
14 def tearDown(self):
15 time.sleep(5)
16 self.driver.quit()
17 self.assertEqual([],self.verificationErrors)
18
19 def test_search(self):
20 """搜索测试关键字"""
21 sp = SearchPage(self.driver)
22 sp.open(self.url)
23 sp.run_case("测试")