之前写过了,在这里:
上周太忙,没啥进度,只是把 Unittest 的文档过了一遍,看下人家是怎么写用例的,链接我贴这儿了:
一个是登录页面的 Page Object,一个是登录功能的测试用例,当然我也没有需求文档,断言都是瞎写的。
from selenium.webdriver.common.by import By
from pages.base_class import BaseClass
from pages.testerhome_home_page import TestHomeHomePage
class TesterHomeSignInPage(BaseClass):
# url
_URL = "http://testerhome.com/"
# locators
_pre_login_btn_loc = (By.CSS_SELECTOR, "a.btn.btn-primary.btn-jumbotron.btn-lg")
_account_input_loc = (By.ID, "user_login")
_password_input_loc = (By.ID, "user_password")
_login_btn_loc = (By.CSS_SELECTOR, "input.btn.btn-primary.btn-lg.btn-block")
# message locators
_error_mes_loc = (By.CSS_SELECTOR, ".alert.alert-warning")
''' actions '''
def _pre_login(self):
self._open_page(self._URL)
self._click_element(self._pre_login_btn_loc)
return self
def _type_username(self, username: str):
self._input_element(self._account_input_loc, username)
return self
def _type_password(self, password: str):
self._input_element(self._password_input_loc, password)
return self
def _submit_login(self):
self._click_element(self._login_btn_loc)
return TestHomeHomePage(self.driver)
def _get_error_message(self):
return self._get_text(self._error_mes_loc, script=self._error_mes_loc[1]) # 这里不够智能,要优化
''' behaviors '''
def login_as(self, username: str, password: str):
self._pre_login() \
._type_username(username) \
._type_password(password)
return self._submit_login()
def login_without_account_password(self):
self._pre_login() \
._click_element(self._login_btn_loc)
return self._get_error_message()
def login_as_wrong_account_password(self):
self._pre_login() \
._type_username("xxxx") \
._type_password("xxxx") \
._click_element(self._login_btn_loc)
return self._get_error_message()
def login_as_missing_account_password(self):
self._pre_login() \
._type_username("somebody") \
._click_element(self._login_btn_loc)
return self._get_error_message()
def repeat_login(self):
self._pre_login() \
._type_username("somebody") \
._type_password("xxxx") \
._click_element(self._login_btn_loc)
self._click_element(self._login_btn_loc)
self._click_element(self._login_btn_loc)
return self._get_error_message()
import unittest
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from pages.testerhome_signin_page import TesterHomeSignInPage
class TestSignIn(unittest.TestCase):
@classmethod
def setUpClass(cls):
service = ChromeService(executable_path=ChromeDriverManager().install())
cls.driver = webdriver.Chrome(service=service)
cls.sign_in_page = TesterHomeSignInPage(cls.driver)
@classmethod
def tearDownClass(cls):
cls.driver.quit()
def test_login_success(self):
home_page = self.sign_in_page.login_as("abc@foxmail.com", "xxxx")
assert home_page.exist()
home_page.logout()
def test_empty_account_password(self):
error_message = self.sign_in_page.login_without_account_password()
self.assertEqual(error_message, "继续操作前请注册或者登录。")
def test_wrong_account_password(self):
error_message = self.sign_in_page.login_as_wrong_account_password()
self.assertEqual(error_message, "账号或密码错误,请重试")
def test_missing_account_password(self):
error_message = self.sign_in_page.login_as_missing_account_password()
self.assertEqual(error_message, "账号或密码错误,请重试")
def test_repeat_login(self):
error_message = self.sign_in_page.repeat_login()
self.assertEqual(error_message, "由于多次密码错误,您的账号已被暂时锁定,一小时后将自动解锁,或者你可以通过邮件手动解锁。")
if __name__ == "__main__":
unittest.main()
text = driver.execute_script("""
return document.querySelector(".alert.alert-warning").lastChild.nodeValue;
""")
Note that the tester still has not done anything but talk about unicorns in this code– no buttons, no locators, no browser controls. This method of modelling the application allows you to keep these test-level commands in place and unchanging, even if Larry decides next week that he no longer likes Ruby-on-Rails and decides to re-implement the entire site in the latest Haskell bindings with a Fortran front-end.