selenium+python自动化测试系列(一):登陆

    最近接手商城的项目,针对后台测试,功能比较简单,可是流程比较繁多,涉及到先后台的交叉测试。在对整个项目进行第一轮测试完成以后,考虑之后回归测试任务比较重,为了减轻回归测试的工做量,因此考虑后台能够进行部分自动化测试。css

    以前一个项目使用robotframework进行回归测试,了解了python语言,因此此次就使用python+selenium进行自动化回归测试了。html

配置环境

  • python2.7
  • 运行工具pycharm2017python

    流程说明

    登陆操做步骤说明web

  1. 打开登陆url,如http://192.168.10.6/login
  2. 在用户名输入框中输入登陆的用户名,如test001
  3. 在密码是输入框中输入密码,如testgood001
  4. 点击登陆页面的登陆按钮,
  5. 登陆成功页面,断言登陆成功

线性操做

根据上面的步骤提示下面代码显示登陆操做,以下浏览器

#coding=utf-8
from selenium import webdriver
import unittest
import sys
reload(sys)
sys.setdefaultencoding('utf8')
class TestLogin(unittest.TestCase):
# 指定浏览器
    def setUp(self):
        self.driver = webdriver.Firefox()
    # 打开url
        self.driver.get("http://192.168.10.6/login")

    # 登陆操做
    def test_login(self):
        title = self.driver.title
        print title
        now_url = self.driver.current_url
        print now_url
        username = "test001"
        password = "testgood001"
        # 执行登陆操做
        #用户名的定位
        self.driver.find_element_by_id("username").clear()
        self.driver.find_element_by_id("username").send_keys(username)
        #密码的定位
        self.driver.find_element_by_id("password").clear()
        self.driver.find_element_by_id("password").send_keys(password)
        # 点击登陆
        self.driver.find_element_by_css_selector(".btn.btn-success.btn-block").click()
        # 登陆成功断言
        login_name = self.driver.find_element_by_xpath('html/body/div[3]/div[2]/ul/li[1]/a/strong').text
        login_name = login_name.strip('您好:')
        assert login_name == username

    # 关闭浏览器
    def tearDown(self):
            self.driver.quit()


if __name__ == "__main__":
unittest.main()

    上面代码显示的是登陆成功的正经常使用例;实际操做中,针对登陆不单单有正经常使用例,还有异经常使用例,如用户名为空,密码为空,用户名错误,密码错误等;咱们不能一个用例编写一个py文件,若是这样操做从本质而言相反增长了工做量。app

    既然问题出来了,那么如何解决这个问题呢?框架

    思路:针对登陆而言,全部的步骤都是同样的,惟一不一样的就是登陆的用户名和密码,因此咱们能够封装登陆步骤,而后只须要专一不一样测试用例中的登陆的用户名和密码的验证便可。dom

    这里为了后续测试的简便,使用了selenium中的po模式,即针对每一个功能的操做页面进行封装,然后在针对该页面进行测试用例的编写。如这里的登陆页面,咱们须要针对登陆页面进行封装操做,把登陆页面中的用户名、密码和登陆按钮的定位进行封装,这样用例中只关注输入不一样的用户名和密码进行验证便可。python2.7

说明:函数

    这里浏览器的打开和关闭也进行了封装,放在myunit.py中。

po模式设计

    总体设计的结构如图所示

    models/driver.py中封装了打开浏览器的操做,这里使用的火狐浏览器进行操做。代码以下

# -*-coding:utf-8-*-
# _author_ = "janehost"
from selenium.webdriver import Remote
from selenium import webdriver
import sys
# 启动浏览器
reload(sys)
sys.setdefaultencoding('utf8')
def browser():
    driver = webdriver.Firefox()
    return driver


if __name__ == '__main__':
        dr = browser()
        dr.get("http://192.168.10.6/login")
        dr.quit()

    models/myunit.py中主要封装了浏览器的启动和关闭的操做,代码以下

# -*-coding:utf-8-*-
# _author_ = "janehost"
import unittest,sys
from selenium import webdriver
from driver import browser
reload(sys)
sys.setdefaultencoding('utf8')

class MyTest(unittest.TestCase):
        def setUp(self):
            self.driver = browser()
            self.driver.implicitly_wait(10)
            self.driver.maximize_window()

        def tearDown(self):
            self.driver.quit()


if __name__ == '__main__':
        unittest.main()

    models/function.py中主要封装了截图的操做方法,代码参考以下

# -*-coding:utf-8-*-
# _author_ = "janehost"
from selenium import webdriver
import os,sys
reload(sys)
sys.setdefaultencoding('utf8')
# 截图函数
def insert_img(driver, file_name):
        base_dir = os.path.dirname(os.path.dirname(__file__))
        base_dir = str(base_dir)
        base_dir = base_dir.replace('\\', '/')
        base = base_dir.split('test_case')[0]
        file_path = base + "report/image/" + file_name
        driver.get_screenshot_as_file(file_path)


if __name__ == '__main__':
        driver = webdriver.Firefox()
        driver.get("http://192.168.10.6/login")
        insert_img(driver, 'login.jpg')
        driver.quit()

    下面就是po模式的重点,针对页面的封装,首先建立一个page页面的基本页面,page_obj\base.py代码以下

# -*-coding:utf-8-*-
# _author_ = "janehost"


from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import sys
reload(sys)
sys.setdefaultencoding('utf8')
class Page(object):

'''
页面基础类,用于全部页面的继承
'''

    base_url = "http://192.168.10.6/login"

    def __init__(self, selenium_driver, base_url=base_url, parent=None):
    self.base_url = base_url
    self.driver = selenium_driver
    self.timeout = 30
    self.parent = parent

def _open(self, url):
    url = self.base_url + url
    self.driver.get(url)
    assert self.on_page(), 'Did not land on %s' % url

def open(self):
    self._open(self.url)

def on_page(self):
    #return (self.driver.current_url).encode('utf-8') == (self.base_url + self.url)
    return self.driver.current_url.encode('utf-8') == (self.base_url + self.url)

def find_element(self, *loc):
    # return self.driver.find_element(*loc)
    try:
    # 确保全部元素是可见的
    # 注意:如下入参为元组的元素,须要加*。python存在这种特性,就是将入参放在元组里。
    #WebDriverWait(self.driver,10).until(lambda driver: driver.find_element(*loc).is_displayed())
    # 注意:如下入参自己是元组,不须要加*
        WebDriverWait(self.driver, 10).until(EC.visibility_of_element_located(loc))
        return self.driver.find_element(*loc)
    except:
        print u"%s 页面中未能找到 %s 元素"%(self, loc)

def find_elements(self, *loc):
    return self.driver.find_elements(*loc)

def script(self, src):
    return self.driver.execute_script(src)

def swtich_frame(self, loc):
    return self.driver.swith_to_frame(loc)

def send_keys(self, loc, value, clear_first=True, click_first=True):
    try:
    # getattr至关于self.loc
        loc = getattr(self, "_%s" % loc)
        if click_first:
            self.find_element(*loc).click()
        if clear_first:
            self.find_element(*loc).clear()
        self.find_element(*loc).send_keys(value)
    except ArithmeticError:
        print u"%s 页面中未能找到 %s 元素" % (self, loc)

    登陆页面元素的封装page_obj\loginPage.py,代码以下

# -*-coding:utf-8-*-
# _author_ = "janehost"
"""
思路:建立登陆页面对象,对用户登陆页面上的用户名/密码输入框、登陆按钮和
提示信息等元素的定位进行封装。
"""
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from base import Page
from time import sleep

class login(Page):

    '''
    用户登陆界面
    '''
    url = '/'
    # 登陆用户名的定位
    login_username_loc = (By.ID, 'username')
    # 登陆密码的定位
    login_password_loc = (By.ID,'password')
    # 登陆按钮的定位
    login_button_loc = (By.CSS_SELECTOR,'.btn.btn-success.btn-block')
    # 登陆错误提示的定位
    login_error_loc = (By.ID,'error_msg')
    # 登陆成功用户名信息
    login_user_success_loc = (By.XPATH, 'html/body/div[3]/div[2]/ul/li[1]/a/strong')

    # 登陆用户名
    def login_username(self, username):
        self.find_element(*self.login_username_loc).clear()
        self.find_element(*self.login_username_loc).send_keys(username)

    # 登陆密码
    def login_password(self, password):
        self.find_element(*self.login_password_loc).clear()
        self.find_element(*self.login_password_loc).send_keys(password)

    # 登陆按钮
    def login_button(self):
    self.find_element(*self.login_button_loc).click()

    # 统一登陆入口
    def user_login(self, username="testuser01", password="testgood001"):
    # 获取用户名和页面登陆
        self.open()
        self.login_username(username)
        self.login_password(password)
        self.login_button()
        sleep(3)

    # 登陆错误提示信息
    def login_error_hint(self):
        return self.find_element(*self.login_error_loc).text

    # 登陆成功用户名信息
    def login_user_success(self):
        #return self.find_element(*self.login_user_success_loc).text
        username = self.find_element(*self.login_user_success_loc).text
        username = username.strip('您好:')
        return username

    登陆测试用例信息test_case\login_sta.py,代码以下

# -*-coding:utf-8-*-
# _author_ = "janehost"
from time import sleep
import unittest, random, sys
from models import myunit, function
from page_obj.loginPage import login
sys.path.append("./models")
sys.path.append("./page_obj")
reload(sys)
sys.setdefaultencoding('utf8')
class loginTest(myunit.MyTest):

    '''
    测试用户登陆
    '''

    def user_login_verify(self, username="", password=""):
        login(self.driver).user_login(username, password)

    def test_login1(self):
    '''用户名、密码为空登陆'''
        self.user_login_verify()
        po = login(self.driver)
        self.assertEqual(po.login_error_hint(), '用户名或密码不能为空')
        function.insert_img(self.driver, "user_pawd_empty.jpg")

    def test_login2(self):
    '''用户名正确,密码为空登陆验证'''
        self.user_login_verify(username="ces")
        po = login(self.driver)
        self.assertEqual(po.login_error_hint(), "用户名或密码不能为空")
        function.insert_img(self.driver,"pawd_empty.jpg")

    def test_login3(self):
    '''用户名为空,密码正确'''
        self.user_login_verify(password="12334ddf")
        po = login(self.driver)
        self.assertEqual(po.login_error_hint(),"用户名或密码不能为空")
        function.insert_img(self.driver, "user_empty.jpg")

    def test_login4(self):
    '''用户名和密码不匹配'''
        character = random.choice('abcdefghijklmnopqrstuvwxyz')
        username = "sdw" + character
        self.user_login_verify(username=username, password="2sdfd")
        po = login(self.driver)
        self.assertEqual(po.login_error_hint(), "用户名或密码错误")
        function.insert_img(self.driver, "user_pass_error.jpg")

    def test_login5(self):
    '''用户名、密码正确'''
        self.user_login_verify(username="adtest" , password="4dscsdx")
        sleep(3)
        po = login(self.driver)
        self.assertEqual(po.login_user_success(), u'adtest')
        function.insert_img(self.driver, "user_pwd_true.jpg")


if __name__ == '__main__':
    unittest.main()

    这样登陆的测试用例就完成了。使用po模式以后,若是页面ui发生变化,咱们只须要修改元素的定位方法,而不须要改动整个框架,相对而言比较快捷。

参考:

小小的博客 [http://www.cnblogs.com/xiaozhiblog/p/5378723.html]

selenium2 python自动化测试实战(虫师)

相关文章
相关标签/搜索