1、页面对象设计模式的概念(PO模式):

创建可以跨多个测试用例共享的代码

减少重复代码的数量

如果用户界面发生了维护,我们只需要维护一个地方,这样修改以及维护的成本相对而言是比较低的

2、目录结构设计

 每个目录的简单介绍:

base:基础层,主要编写的是底层元素封装

page:对象层,主要指的是页面的每一个交互写成一个独立的方法

test:测试层,里面主要编写测试用例

common:公共方法,把公共的方法分离到这个里面

utils:工具类,主要指的是操作有一些工具的类

data:把测试过程中的数据存储在这个目录下

report:测试报告,主要指的是存储生成的HTML的测试报告

3、实现基础层的代码,在base包下创建模块为base.py的文件,里面的源码信息为:

 1 from selenium.webdriver.support.expected_conditions import NoSuchElementException
 2 
 3 class WebDriver(object):
 4     def __init__(self,driver):
 5         # self.driver=webdriver.Chrome()
 6         # self.driver是driver实例化后的对象
 7         self.driver=driver
 8 
 9     def findElement(self,*loc):
10         '''单个元素定位的方式'''
11         try:
12             #*loc既表示括号里边是动态参数,也表示括号中的元素是元组类型
13             return self.driver.find_element(*loc)
14         except NoSuchElementException as e:
15             return e.args[0]
16 
17     def findElements(self,*loc):
18         '''多个元素的定位方式'''
19         try:
20             return self.driver.find_element(*loc)
21         except NoSuchElementException as e:
22             return e.args[0]

4、实现对象层的代码,以新浪登录页面为例,在page包下面新建一个login的文件,代码如下:

 1 from selenium.webdriver.common.by import By
 2 from base.base import WebDriver
 3 import time as t
 4 
 5 class Login(WebDriver):
 6     username=(By.ID,'freename')
 7     password=(By.ID,'freepassword')
 8     loginButton=(By.LINK_TEXT,'登录')
 9     userInfo=(By.XPATH,'/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]')
10     passwordInfo=(By.XPATH,'/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[2]')
11     emailInfo=(By.XPATH,'//*[@id="user_id"]/em[2]')
12     isAutoLogin=(By.ID,'store1')
13 
14     def inputUsername(self,username):
15         t.sleep(3)
16         self.findElement(*self.username).send_keys(username)
17 
18     def inputPassword(self,password):
19         t.sleep(3)
20         self.findElement(*self.password).send_keys(password)
21 
22     def clickLogin(self):
23         t.sleep(3)
24         self.findElement(*self.loginButton).click()
25 
26     def getUserDev(self):
27         '''获取账户的错误提示信息'''
28         t.sleep(3)
29         return self.findElement(*self.userInfo).text
30 
31     def getPassword(self):
32         '''获取密码的错误提示信息'''
33         t.sleep(3)
34         return self.findElement(*self.passwordInfo).text
35 
36     def getEmailInfo(self):
37         '''获取登录成功的账户信息'''
38         t.sleep(3)
39         return self.findElement(*self.emailInfo).text
40 
41     def autoLogin(self):
42         '''验证自动登录是否勾选'''
43         t.sleep(3)
44         self.findElement(*self.isAutoLogin).is_selected()
45 
46     def autoLoginCancel(self):
47         '''验证自动登录是否取消勾选'''
48         t.sleep(3)
49         self.findElement(*self.isAutoLogin).click()
50 
51     def login(self,username,password):
52         self.inputUsername(username=username)
53         self.inputPassword(password=password)
54         self.clickLogin()

5、实现测试层的代码,以新浪登录页面为例,在test包下面新建一个test_login的文件,代码如下:

 1 import unittest
 2 from selenium import webdriver
 3 from page.login import Login
 4 from utils.operationJson import readJson
 5 
 6 class TestLogin(unittest.TestCase,Login):
 7     def setUp(self) -> None:
 8         self.driver=webdriver.Chrome()
 9         self.driver.maximize_window()
10         self.driver.get("https://mail.sina.com.cn/#")
11         self.driver.implicitly_wait(30)
12 
13     def tearDown(self) -> None:
14         self.driver.quit()
15 
16     def test_username_null(self):
17         '''登录验证:账户为空错误提示信息验证'''
18         self.login(username='',password='')
19         self.assertEqual(self.getuserDev(),readJson()['nullEmail'])
20 
21     def test_email_format_error(self):
22         '''登录验证:验证邮箱格式错误'''
23         self.login(username='gfs',password='hhhhf')
24         self.assertEqual(self.getuserDev(),readJson()['formatEmail'])
25 
26     def test_username_password_error(self):
27         '''登录验证:验证登录账户错误'''
28         self.login(username='gfhhgh@sina.com',password='xgfj')
29         self.assertEqual(self.getuserDev(),readJson()['loginError'])
30 
31     def test_password_null(self):
32         '''登录验证:验证密码为空错误提示信息'''
33         self.login(username='wuya1303@sina.com',password='')
34         self.assertEqual(self.getPasswdDev(),readJson()['nullPassword'])
35 
36     def test_login_success(self):
37         '''登录验证:验证登录成功的账户'''
38         self.login(username='wuya1303@sina.com',password='admin123')
39         self.assertEqual(self.getEmailDev(),"wuya1303@sina.com")
40 
41     def test_auto_login(self):
42         '''登录验证:验证自动登录是否勾选'''
43         self.assertTrue(self.autoLogin())
44 
45     def test_auto_login_cancel(self):
46         '''登录验证:验证自动登录是否取消勾选'''
47         self.clickAutoLogin()
48         self.assertFalse(self.autoLogin())
49 
50 if __name__ == '__main__':
51     unittest.main()

通过主函数入口,运行测试层的代码,得到的结果如下:

 6、公共方法

在common包下创建public.py的模块,并编写针对文件路径的处理,具体源码如下:

 1 import os
 2 
 3 def base_dir():
 4     return os.path.dirname(os.path.dirname(__file__))
 5 
 6 def filePath(directory,filename):
 7     # 获取文件的详细路径
 8     # directory:目录
 9     # filename:文件名称
10     return os.path.join(base_dir(),directory,filename)

7、数据驱动

在data的文件夹下创建sina.json的文件,把登录使用到的数据分离到sina.json的文件里面,文件内容如下:

1 {
2   "nullEmail":"请输入邮箱名",
3   "formatEmail": "您输入的邮箱名格式不正确",
4   "loginError":"登录名或密码错误",
5   "nullPassword":"请输入密码"
6 }

8、工具类

在具体的工具类中编写针对JSON文件的处理,创建的模块名称为:operationJson.py,具体源码为:

 1 import unittest
 2 import os
 3 import HTMLTestRunner
 4 from common.public import*
 5 import time
 6 
 7 def allTests():
 8     #获取要执行的测试模块
 9     suite=unittest.TestLoader().discover(
10     #start_dir指的是测试模块的路径
11         start_dir=os.path.join(base_dir(),'test'),
12     #pattern通过正则方式加载所有测试模块
13         pattern="test_*.py")
14     return suite
15 
16 def getNowTime():
17     return time.strftime('%y-%m-%d %H_%M_%S',time.localtime(time.time()))
18 
19 def run():
20     filename=os.path.join(os.path.dirname(__file__),'report',getNowTime()+'.html')
21     fp=open(filename,"wb")
22     runner=HTMLTestRunner.HTMLTestRunner(
23         stream=fp,
24         title='UI自动化测试',
25         description='ui test'
26     )
27     runner.run(allTests())
28 
29 if __name__ == '__main__':
30     run()

运行代码后的结果如下:

 9、新浪首页注册实战

1)对象层代码如下:

 1 from selenium.webdriver.common.by import By
 2 import time as t
 3 from base.base import WebDriver
 4 
 5 class Register(WebDriver):
 6     register=(By.CLASS_NAME,'registerBtn')
 7     agree=(By.NAME,'agreement')
 8     register_right_away=(By.XPATH,'/html/body/div[2]/div/div/div/div/form[1]/div[3]/ul/li/div/div/a')
 9     email_null=(By.XPATH,'/html/body/div[2]/div/div/div/div/form[1]/div[2]/ul/li[1]/div[3]/p/abbr')
10 
11     def clickRegister(self):
12         t.sleep(3)
13         self.findElement(*self.register).click()
14 
15     def clickAgree(self):
16         t.sleep(3)
17         self.findElement(*self.agree).click()
18 
19     def clickRegisterAway(self):
20         t.sleep(3)
21         self.findElement(*self.register_right_away).click()
22 
23     def clickReg(self):
24         self.clickAgree()
25         self.clickRegisterAway()
26 
27     def getEmail(self):
28         t.sleep(3)
29         return self.findElement(*self.email_null).text

2)测试层代码如下:

 1 from selenium import webdriver
 2 from page.register import Register
 3 from utils.operationJson import readJson
 4 import unittest
 5 import time as t
 6 class TestRegister(unittest.TestCase,Register):
 7     def setUp(self) -> None:
 8         self.driver=webdriver.Chrome()
 9         self.driver.maximize_window()
10         self.driver.get('https://mail.sina.com.cn/#')
11         self.driver.implicitly_wait(30)
12 
13     def tearDown(self) -> None:
14         self.driver.quit()
15 
16     def test_email_null(self):
17         '''注册验证:邮箱为空错误提示信息验证'''
18         nowHandler=self.driver.current_window_handle
19         self.clickRegister()
20         t.sleep(3)
21         allHandlers=self.driver.window_handles
22         t.sleep(3)
23         for handler in allHandlers:
24             if handler!=nowHandler:
25                 self.driver.switch_to.window(handler)
26                 self.clickReg()
27         self.assertEqual(self.getEmail(),readJson()['nullEmail'])
28 
29 if __name__ == '__main__':
30     unittest.main()

运行测试层代码后的结果如下: