背景

之前写过了,在这里:

目标

  1. 测试登录功能

备注

上周太忙,没啥进度,只是把 Unittest 的文档过了一遍,看下人家是怎么写用例的,链接我贴这儿了:

正文

代码

一个是登录页面的 Page Object,一个是登录功能的测试用例,当然我也没有需求文档,断言都是瞎写的。

testerhome_signin_page.py

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()

test_signin.py

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()

效果图

发现问题

  1. 登录页面的结构,是这个样子的: 假如我直接取 element.text,会获取到所有子节点的 text,即会包含一个"x\n",造成断言失败: 网上查了一下,只找到注入 javascript 代码来实现,不太灵活,先记着,有空再优化。(不好意思,我忘了在哪儿看到的了,没链接) text = driver.execute_script(""" return document.querySelector(".alert.alert-warning").lastChild.nodeValue; """)
  2. 第二个问题,其实也不算是个问题,算是感想。 如备注所说,其实上周我自己没写多少,都看别人写的代码。 网友们推荐的网站看了,推荐的框架也看了,可惜我水平还不够,连说明文档里的示例也没看懂,还要继续努力才行。 周末写着写着代码,突然很迷茫,这个自动化到底是在写脚本,还是在做测试?我是不是明知这个功能是正常的,才去实现自动化? 于是我又把 Selenium 的文档看了一遍,里面有这么一段话,可能是一种答案,分享给大家。

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.


↙↙↙阅读原文可查看相关链接,并与作者交流