Selenium+Python自动化测试:登录

发表于:2019-5-31 10:59

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:janehost    来源:博客园

  最近接手商城的项目,针对后台测试,功能比较简单,但是流程比较繁多,涉及到前后台的交叉测试。在对整个项目进行第一轮测试完成之后,考虑以后回归测试任务比较重,为了减轻回归测试的工作量,所以考虑后台可以进行部分自动化测试
  之前一个项目使用robotframework进行回归测试,了解了python语言,所以这次就使用python+selenium进行自动化回归测试了。
  配置环境
  python2.7
  运行工具pycharm2017
  流程说明
  登录操作步骤说明
  打开登录url,如http://192.168.10.6/login
  在用户名输入框中输入登录的用户名,如test001
  在密码是输入框中输入密码,如testgood001
  点击登录页面的登录按钮,
  登录成功页面,断言登录成功
  线性操作
  根据上面的步骤提示下面代码显示登录操作,如下
   #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文件,如果这样操作从本质而言相反增加了工作量。
  既然问题出来了,那么如何解决这个问题呢?
  思路:针对登录而言,所有的步骤都是一样的,唯一不同的就是登录的用户名和密码,所以我们可以封装登录步骤,然后只需要专注不同测试用例中的登录的用户名和密码的验证即可。
  这里为了后续测试的简便,使用了selenium中的po模式,即针对每个功能的操作页面进行封装,而后在针对该页面进行测试用例的编写。如这里的登录页面,我们需要针对登录页面进行封装操作,把登录页面中的用户名、密码和登录按钮的定位进行封装,这样用例中只关注输入不同的用户名和密码进行验证即可。
  说明:
   这里浏览器的打开和关闭也进行了封装,放在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发生变化,我们只需要修改元素的定位方法,而不需要改动整个框架,相对而言比较快捷。

      上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号