python+selenium+unittest+HTMLTestRunner读取csv文件参数化登陆测试

之前尝试了Python+selenium+unittest+HTMLTestRunner(传送门)写了登陆脚本,然后又看了参数化及循环,于是决定写个参数化的登陆脚本。当然遇到问题是在所难免的,几经周折,最后还是完成了参数化脚本。所以写下本帖记录一下,方便以后查阅。现在先来分析一下脚本出现的问题,一开始脚本是这样的:


   
   
  1. #构建登陆类,用unittest框架,所以是unittest.testCase
  2. class test(unittest.TestCase):
  3. #构建登陆异常的方法
  4. def test_login(self):
  5. dr=webdriver.Chrome() #调用谷歌浏览器,其他浏览器更改drvier
  6. #需要测试的网页
  7. dr.get( 'https://passport.cnblogs.com/user/signin')
  8. #构建参数化,格式为[[,,,],[,,,],[,,,]...[,,,],
  9. #最外面[]里的每个[]为一条用例,每条用例的项用,隔开
  10. user_pass=[[ '1', '1', '错误的用户名登陆', 'login_username_error', 'lblUserNameError', u'用户名错误!'],
  11. [ '', '123456', '不输入用户名登陆', 'login_username_null', 'lblUserNameError', u'请输入用户名!'],
  12. [ 'testuser', '1', '错误的密码登陆', 'login_password_error', 'lblUserPwdError', u'密码错误'],
  13. [ '1', '', '不输入密码登陆', 'login_username_null', 'lblUserPwdError', u'请输入密码!']]
  14. #参数化定义变量,变量名自定义,数量为需要变量的数量
  15. #最多不超过参数化的数量,顺序与定义参数化的值顺序一致
  16. for (a,b,c,d,e,f) in user_pass:
  17. #输入用户名,定义a在最前面,所以对应用例的一个值
  18. #find_element_by_id里的值为网页抓取到的元素
  19. dr.find_element_by_id( 'input1').send_keys(a)
  20. #输入密码,b为参数化的密码
  21. dr.find_element_by_id( 'input2').send_keys(b)
  22. #点击登陆,click()为点击事件
  23. dr.find_element_by_id( 'signin').click()
  24. sleep( 1)
  25. print (c) #c为参数化的测试目的
  26. #get_screenshot_as_file为截图方法,path为路径
  27. #d为参数化的图片名
  28. dr.get_screenshot_as_file(path+d+ ".jpg")
  29. #先验证提示类型是否正确,e为会显示错误信息的id元素
  30. assert dr.find_element_by_id(e).text, '提示信息类型错误!'
  31. #如果提示类型正确,就会有错误信息,将错误信息赋值给定义的变量
  32. error_message = dr.find_element_by_id(e).text
  33. #asserEqual()是unittest框架中的一种断言,比较两个值是否相等
  34. #f为参数化预期值
  35. self.assertEqual(error_message,f)
  36. #refresh()为浏览器刷新
  37. dr.refresh()

脚本构建在这里,基本算是完成了,当然完整脚本还要加上import包,还有HTMLTestRunner框架生成报告。但是脚本运行的时候,只运行了一次,后面的参数化没运行。当时好郁闷,查阅各种资料,尝试简单的for循环,发现语句没有出现问题,可就是只运行了一次。然后我就找参数化的原因(也怪自己,想看异常结果,所以参数化故意写错,而且还是第一个),结果一改正,哈哈哈~~脚本跑起来了,原来在for循环的时候,出现错误或者预期与实际不匹配,循环就会结束,不会跳转到下一循环。


想象这样肯定是不行的,测试就是确认和验证预期结果与实际结果的比较,一不对就停止循环,无法实现自动化测试。于是就开始调试脚本,最后想到抛出异常(抛出异常后,即使错误脚本也会默认pass),所以脚本加入try...except...


于是脚本被改成了这样(为了报告更直观,所以加了大量的print显示):


   
   
  1. ......
  2. try:
  3. assert dr.find_element_by_id(e).text
  4. try:
  5. error_message = dr.find_element_by_id(e).text
  6. self.assertEqual(error_message,f)
  7. print( '提示信息正确!预期值与实际值一致:')
  8. print( '预期值:'+f)
  9. print( '实际值:'+error_message)
  10. except:
  11. print ( '提示信息错误!预期值与实际值不符:')
  12. print ( '预期值:'+e)
  13. print( '实际值:'+error_message)
  14. except
  15. print ( '提示信息类型错误,请确认元素名称是否正确!')

脚本终于完善了,又发现之前参数化的内容,少了还好,多了维护起来就很不方便了,于是有想到了python可以读取csv文件,于是将参数文件格式改成这样:


   
   
  1. #要读取的scv文件路径,my_file为自定义变量
  2. my_file= 'C:\\Users\\Administrator\\Desktop\\login1.csv'
  3. #csv.reader()读取csv文件,
  4. #Python3.X用open,Python2.X用file,'r'为读取
  5. #open(file,'r')中'r'为读取权限,w为写入,还有rb,wd等涉及到编码的读写属性
  6. data=csv.reader(open(my_file, 'r'))
  7. #user[0]表示csv文件的第一列,user[1]表示第二列,user[N]表示第N列

新建excel文件按( A列为用户名,B列为密码,C列为测试目的,D列为截图名称,E列为各元素id名,F列为预期值)格式写入用例内容(根据实际情况修改和变化位置),另存为逗号隔开的csv文件即可:


经过几次调整,终于一份完整的脚本写好了,以下就是完整的参数化脚本:


    
    
  1. #coing=utf-8
  2. import csv #导入scv库,可以读取csv文件
  3. from selenium import webdriver
  4. import unittest
  5. from time import sleep
  6. import time
  7. import os
  8. dr=webdriver.Chrome()
  9. class test(unittest.TestCase):
  10. def test_login(self):
  11. '''登陆测试'''
  12. #要读取的scv文件路径
  13. my_file= 'C:\\Users\\Administrator\\Desktop\\login1.csv'
  14. #csv.reader()读取csv文件,
  15. #Python3.X用open,Python2.X用file,'r'为读取
  16. #open(file,'r')中'r'为读取权限,w为写入,还有rb,wd等涉及到编码的读写属性
  17. data=csv.reader(open(my_file, 'r'))
  18. #for循环将读取到的csv文件的内容一行行循环,这里定义了user变量(可自定义)
  19. #user[0]表示csv文件的第一列,user[1]表示第二列,user[N]表示第N列
  20. #for循环有个缺点,就是一旦遇到错误,循环就停止,所以用try,except保证循环执行完
  21. for user in data:
  22. dr.get( 'https://passport.cnblogs.com/user/signin')
  23. #dr.find_element_by_id('input1').clear()
  24. dr.find_element_by_id( 'input1').send_keys(user[ 0])
  25. #dr.find_element_by_id('input2').clear()
  26. dr.find_element_by_id( 'input2').send_keys(user[ 1])
  27. dr.find_element_by_id( 'signin').click()
  28. sleep( 1)
  29. print ( '\n'+ '测试项:'+user[ 2])
  30. dr.get_screenshot_as_file(path+user[ 3]+ ".jpg")
  31. try:
  32. assert dr.find_element_by_id(user[ 4]).text
  33. try:
  34. error_message = dr.find_element_by_id(user[ 4]).text
  35. self.assertEqual(error_message,user[ 5])
  36. print( '提示信息正确!预期值与实际值一致:')
  37. print( '预期值:'+user[ 5])
  38. print( '实际值:'+error_message)
  39. except:
  40. print ( '提示信息错误!预期值与实际值不符:')
  41. print ( '预期值:'+user[ 5])
  42. print( '实际值:'+error_message)
  43. except:
  44. print ( '提示信息类型错误,请确认元素名称是否正确!')
  45. def tearDown(self):
  46. dr.refresh()
  47. if __name__== '__main__':
  48. #导入HTMLTestRunner库,这句也可以放在脚本开头
  49. from HTMLTestRunner import HTMLTestRunner
  50. #定义脚本标题,加u为了防止中文乱码
  51. report_title = u'登陆模块测试报告'
  52. #定义脚本内容,加u为了防止中文乱码
  53. desc = u'登陆模块测试报告详情:'
  54. #定义date为日期,time为时间
  55. date=time.strftime( "%Y%m%d")
  56. time=time.strftime( "%Y%m%d%H%M%S")
  57. #定义path为文件路径,目录级别,可根据实际情况自定义修改
  58. path= 'D:/Python_test/'+ date + "/login/"+time+ "/"
  59. #定义报告文件路径和名字,路径为前面定义的path,名字为report(可自定义),格式为.html
  60. report_path = path+ "report.html"
  61. #判断是否定义的路径目录存在,不能存在则创建
  62. if not os.path.exists(path):
  63. os.makedirs(path)
  64. else:
  65. pass
  66. #定义一个测试容器
  67. testsuite = unittest.TestSuite()
  68. #将测试用例添加到容器
  69. testsuite.addTest(test( "test_login"))
  70. #将运行结果保存到report,名字为定义的路径和文件名,运行脚本
  71. with open(report_path, 'wb') as report:
  72. runner = HTMLTestRunner(stream=report, title=report_title, description=desc)
  73. runner.run(testsuite)
  74. #关闭report,脚本结束
  75. report.close()
  76. #关闭浏览器
  77. dr.quit()


效果图(还是很一目了然的~哈哈哈哈~~~):


发布了17 篇原创文章 · 获赞 1 · 访问量 819

猜你喜欢

转载自blog.csdn.net/weixin_45433031/article/details/104957429
今日推荐