[关闭]
@huis 2016-09-26T15:14:07.000000Z 字数 4471 阅读 121

Python Selenium学习笔记1

python unittest selenium thead


如何运行单元测试时只运行一个浏览器,而不是每个TestCase都打开一个浏览器

具体实现方法:

  1. class BaseUnitTest(unittest.TestCase):
  2. # --实例属性区--
  3. """是否开启TestCase级别的单驱动模式,默认False
  4. 开启时, 一个TestCase只会打开一个浏览器,也就是method之间是公用浏览器,
  5. 而不是每个测试Method都打开一个浏览器
  6. """
  7. SINGLE_DRIVER = False
  8. # --类方法区--
  9. @classmethod
  10. def setUpClass(cls):
  11. cls.driver = None
  12. @classmethod
  13. def tearDownClass(cls):
  14. if cls.SINGLE_DRIVER:
  15. BaseUnitTest.__quit_driver(cls.driver)
  16. # --静态方法区--
  17. @staticmethod
  18. def __new_driver():
  19. driver = browser(env.BROWSER, env.DRIVER_PATH)
  20. driver.maximize_window()
  21. return driver
  22. @staticmethod
  23. def __quit_driver(driver):
  24. if env.BROWSER.upper() == 'PHANTOMJS':
  25. # 这里是为了能够真正的退出
  26. driver.service.process.send_signal(signal.SIGTERM)
  27. driver.quit()
  28. def setUp(self):
  29. if self.SINGLE_DRIVER:
  30. if self.__class__.driver is None:
  31. self.driver = BaseUnitTest.__new_driver()
  32. self.__class__.SINGLE_DRIVER = self.SINGLE_DRIVER
  33. self.__class__.driver = self.driver
  34. else:
  35. self.driver = self.__class__.driver
  36. else:
  37. self.driver = BaseUnitTest.__new_driver()
  38. def tearDown(self):
  39. if not self.SINGLE_DRIVER:
  40. BaseUnitTest.__quit_driver(self.driver)

如何用多线程运行Selenium测试

  • threading.Thread线程方式,这种方式需要注意的是多个线程之间的相互影响,导致共享值的变化,下面是实现方式(这种有问题,就是不知道合适的时机和方式去关闭driver):
  1. # coding=utf-8
  2. import unittest
  3. import threading
  4. from driver import browser
  5. import env
  6. import signal
  7. import utils
  8. import dataUtils
  9. import sys
  10. from time import ctime
  11. class BaseUnitTest(unittest.TestCase):
  12. # --实例属性区--
  13. """是否开启TestCase级别的单驱动模式,默认False
  14. 开启时, 一个TestCase只会打开一个浏览器,也就是method之间是公用浏览器,
  15. 而不是每个测试Method都打开一个浏览器
  16. """
  17. SINGLE_DRIVER = False
  18. # --类方法区--
  19. @classmethod
  20. def setUpClass(cls):
  21. env.thread_local.SINGLE_DRIVER = cls.SINGLE_DRIVER
  22. @classmethod
  23. def tearDownClass(cls, is_thread=False):
  24. if is_thread and env.thread_local.SINGLE_DRIVER:
  25. BaseUnitTest.__quit_driver(env.thread_local.driver)
  26. # --静态方法区--
  27. @staticmethod
  28. def __new_driver():
  29. driver = browser(env.BROWSER, env.DRIVER_PATH)
  30. driver.maximize_window()
  31. return driver
  32. @staticmethod
  33. def __quit_driver(driver):
  34. if env.BROWSER.upper() == 'PHANTOMJS':
  35. # 这里是为了能够真正的退出
  36. driver.service.process.send_signal(signal.SIGTERM)
  37. driver.quit()
  38. # --实例方法区--
  39. # 1.重写父类区
  40. def __init__(self, methodName='runTest'):
  41. ''' overide the TestCase __init__ Method
  42. so need to recall the TestCase __init__ method
  43. '''
  44. super(BaseUnitTest, self).__init__(methodName)
  45. self.__testMethodName = methodName
  46. def setUp(self):
  47. if env.thread_local.SINGLE_DRIVER:
  48. if env.thread_local.driver is None:
  49. env.thread_local.driver = BaseUnitTest.__new_driver()
  50. self.driver = env.thread_local.driver
  51. else:
  52. self.driver = BaseUnitTest.__new_driver()
  53. def tearDown(self):
  54. if not env.thread_local.SINGLE_DRIVER:
  55. BaseUnitTest.__quit_driver(self.driver)
  56. # 2.自定义方法区
  57. def assertEqualUnicode(self, a, b):
  58. a = dataUtils.decodeToUnicode(a)
  59. b = dataUtils.decodeToUnicode(b)
  60. self.assertEqual(a, b)
  61. # 3.私有方法区
  62. def __exc_info(self):
  63. ''' copy from TestCase ,aim to overide the TestCase __call__ method
  64. '''
  65. exctype, excvalue, tb = sys.exc_info()
  66. if sys.platform[:4] == 'java': # tracebacks look different in Jython
  67. return (exctype, excvalue, tb)
  68. newtb = tb.tb_next
  69. if newtb is None:
  70. return (exctype, excvalue, tb)
  71. return (exctype, excvalue, newtb)
  72. def __call__(self, result=None):
  73. ''' overide the TestCase __call__ method
  74. aim to add insert_img_decorator to the test_case method
  75. '''
  76. if result is None:
  77. result = self.defaultTestResult()
  78. result.startTest(self)
  79. testMethod = getattr(self, self.__testMethodName)
  80. newMethod = utils.insert_img_decorator(
  81. self.__testMethodName)(testMethod)
  82. try:
  83. try:
  84. self.setUp()
  85. except KeyboardInterrupt:
  86. raise
  87. except:
  88. result.addError(self, self.__exc_info())
  89. return
  90. ok = 0
  91. try:
  92. newMethod(self)
  93. ok = 1
  94. except self.failureException, e:
  95. result.addFailure(self, self.__exc_info())
  96. except KeyboardInterrupt:
  97. raise
  98. except:
  99. result.addError(self, self.__exc_info())
  100. try:
  101. self.tearDown()
  102. except KeyboardInterrupt:
  103. raise
  104. except:
  105. result.addError(self, self.__exc_info())
  106. ok = 0
  107. if ok:
  108. result.addSuccess(self)
  109. finally:
  110. result.stopTest(self)
  • multiprocessing进程方式,这种方式可以避免线程上的值共享被共同访问时的问题,但是需要注意其他问题,就是测试结果如何共享的问题,实现代码如上

unittest执行过程分析-TestLoader

TestLoader.discover发现的结果如下:

  1. <unittest.suite.TestSuite
  2. tests=[
  3. <unittest.suite.TestSuite
  4. tests=[
  5. <unittest.suite.TestSuite tests=[]>,
  6. <unittest.suite.TestSuite
  7. tests=[
  8. <exam_manager_test.ExamManageTest testMethod=test_a_add_exam>,
  9. <exam_manager_test.ExamManageTest testMethod=test_b_search_exam>
  10. ]
  11. >
  12. ]
  13. >,
  14. <unittest.suite.TestSuite
  15. tests=[
  16. <unittest.suite.TestSuite tests=[]>,
  17. <unittest.suite.TestSuite
  18. tests=[
  19. <exam_manager_1_test.ExamManageTest testMethod=test_c_add_exam>,
  20. <exam_manager_1_test.ExamManageTest testMethod=test_d_search_exam>
  21. ]
  22. >
  23. ]
  24. >
  25. ]
  26. >

数据知道了,那具体流程图如下:

Created with Raphaël 2.1.2StartTestSuite RunIterator TestSuiteIs TestSuite?TestCase TearDownPreClassTestCase SetUpModuleTestCase SetUpClassTestCase SetUpTestCase RunTestCase TearDownIs Last TestCase?TestCase TearDownClassTestCase TearDownModuleEndyesnoyesno
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注