|
1 | 1 | # AutomatedTestingDemo
|
2 | 2 | 自动化测试框架测试Demo
|
3 | 3 |
|
4 |
| -## Android APP 自动化测试框架 |
| 4 | +### Android APP 自动化测试 |
5 | 5 |
|
6 |
| -### 自动化测试环境安装 |
| 6 | +#### 自动化测试环境安装 |
7 | 7 |
|
8 | 8 | - Node.js - [下载地址]( https://nodejs.org/en/download/)
|
9 | 9 |
|
|
21 | 21 |
|
22 | 22 | > 软件安装以及环境配置可以参考这篇文章:[参考文章](https://blog.csdn.net/zh175578809/article/details/76780054)
|
23 | 23 |
|
| 24 | +#### 编写自动化测试Demo |
| 25 | + |
| 26 | +下面的demo是对系统自带的计算器APP进行测试的,界面元素的id和包名都是通过UIAutomator获取的。 |
| 27 | + |
| 28 | +```python |
| 29 | +from appium import webdriver |
| 30 | + |
| 31 | +desired_caps = {} |
| 32 | +desired_caps['platformName'] = 'Android' |
| 33 | +desired_caps['platformVersion'] = '9.0' |
| 34 | +desired_caps['deviceName'] = '192.168.115.101:5555' |
| 35 | +desired_caps['appPackage'] = 'com.android.calculator2' |
| 36 | +desired_caps['appActivity'] = '.Calculator' |
| 37 | +desired_caps["unicodeKeyboard"] = "True" |
| 38 | +desired_caps["resetKeyboard"] = "True" |
| 39 | +driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) |
| 40 | + |
| 41 | +driver.find_element_by_id("digit_1").click() |
| 42 | +driver.find_element_by_id("digit_3").click() |
| 43 | +driver.find_element_by_id("digit_5").click() |
| 44 | +driver.find_element_by_id("op_add").click() |
| 45 | +driver.find_element_by_id("digit_8").click() |
| 46 | +driver.find_element_by_id("digit_9").click() |
| 47 | +driver.find_element_by_id("op_mul").click() |
| 48 | +driver.find_element_by_id("digit_3").click() |
| 49 | +driver.find_element_by_id("digit_9").click() |
| 50 | +driver.find_element_by_id("digit_2").click() |
| 51 | +driver.find_element_by_id("eq").click() |
| 52 | + |
| 53 | +result = driver.find_element_by_id("result").text |
| 54 | + |
| 55 | +if result == "30,352": |
| 56 | + print "pass" |
| 57 | +else: |
| 58 | + print "fail" |
| 59 | + |
| 60 | +# 一定记得退出driver,不然下次运行会直接报错,除非在Appium中手动停止连接 |
| 61 | +driver.quit() |
| 62 | +``` |
| 63 | + |
| 64 | +先运行Appium,点击android图标进行设置,主要设置platformVersion,我是用的Appium版本为appium1.4.16,由于appium1.4.16版本最高只支持安卓6.0版本,所以可以[参考这篇文章](https://www.jianshu.com/p/0136e26eee36)进行一些修改设置,然后运行Appium启动连接,再运行上面的demo,可以得到下面的输出结果: |
| 65 | + |
| 66 | +``` |
| 67 | +E:\Python27\python.exe F:/code/AutomatedTestingDemo/test_demo/test_demo.py |
| 68 | +35,023 |
| 69 | +
|
| 70 | +Process finished with exit code 0 |
| 71 | +``` |
| 72 | + |
| 73 | +### Android APP 自动化测试框架 |
| 74 | + |
| 75 | +#### Unittest框架 |
| 76 | + |
| 77 | +> 使用unittest编写用例,必须遵守以下规则: |
| 78 | +> |
| 79 | +> 1、测试文件必须先import unittest; |
| 80 | +> |
| 81 | +> 2、测试类必须继承unittest.TestCase; |
| 82 | +> |
| 83 | +> 3、测试方法必须以“test_”开头; |
| 84 | +> |
| 85 | +> 4、测试类必须要有unittest.main()方法。 |
| 86 | +
|
| 87 | +##### Test Fixture |
| 88 | + |
| 89 | +> A test fixture represents the preparation needed to perform one or more tests, and any assoicate cleanup actions. |
| 90 | +
|
| 91 | +- setUp() : 进行测试前的初始化工作。 |
| 92 | +- testCase() : 进行测试工作,可以有很多个 |
| 93 | +- tearDown() : 执行测试后的清除工作。 |
| 94 | + |
| 95 | +使用unittest改写上面的自动化测试脚本 |
| 96 | + |
| 97 | +```python |
| 98 | +import unittest |
| 99 | +from appium import webdriver |
| 100 | + |
| 101 | + |
| 102 | +class MyTestCase(unittest.TestCase): |
| 103 | + |
| 104 | + def setUp(self): |
| 105 | + desired_caps = {} |
| 106 | + desired_caps['platformName'] = 'Android' |
| 107 | + desired_caps['platformVersion'] = '9.0' |
| 108 | + desired_caps['deviceName'] = '192.168.115.101:5555' |
| 109 | + desired_caps['appPackage'] = 'com.android.calculator2' |
| 110 | + desired_caps['appActivity'] = '.Calculator' |
| 111 | + desired_caps["unicodeKeyboard"] = "True" |
| 112 | + desired_caps["resetKeyboard"] = "True" |
| 113 | + self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) |
| 114 | + |
| 115 | + def test_something(self): |
| 116 | + self.driver.find_element_by_id("digit_1").click() |
| 117 | + self.driver.find_element_by_id("digit_3").click() |
| 118 | + self.driver.find_element_by_id("digit_5").click() |
| 119 | + self.driver.find_element_by_id("op_add").click() |
| 120 | + self.driver.find_element_by_id("digit_8").click() |
| 121 | + self.driver.find_element_by_id("digit_9").click() |
| 122 | + self.driver.find_element_by_id("op_mul").click() |
| 123 | + self.driver.find_element_by_id("digit_3").click() |
| 124 | + self.driver.find_element_by_id("digit_9").click() |
| 125 | + self.driver.find_element_by_id("digit_2").click() |
| 126 | + self.driver.find_element_by_id("eq").click() |
| 127 | + |
| 128 | + result = self.driver.find_element_by_id("result").text |
| 129 | + self.assertEqual(result, "35,023") |
| 130 | + |
| 131 | + def tearDown(self): |
| 132 | + # 一定记得退出driver,不然下次运行会直接报错,除非在Appium中手动停止连接 |
| 133 | + self.driver.quit() |
| 134 | + |
| 135 | + |
| 136 | +if __name__ == '__main__': |
| 137 | + unittest.main() |
| 138 | +``` |
| 139 | + |
| 140 | +运行结果: |
| 141 | + |
| 142 | +``` |
| 143 | +Testing started at 11:56 ... |
| 144 | +E:\Python27\python.exe "E:\Program Files\JetBrains\PyCharm Community Edition 2019.1.3\helpers\pycharm\_jb_unittest_runner.py" --target unittestdemo.MyTestCase |
| 145 | +Launching unittests with arguments python -m unittest unittestdemo.MyTestCase in F:\code\AutomatedTestingDemo |
| 146 | +
|
| 147 | +
|
| 148 | +Ran 1 test in 16.699s |
| 149 | +
|
| 150 | +OK |
| 151 | +
|
| 152 | +Process finished with exit code 0 |
| 153 | +``` |
| 154 | + |
| 155 | +##### Test Case & Test Suite &Test Runner |
| 156 | + |
| 157 | +官网的含义介绍: |
| 158 | + |
| 159 | +> A test case is the smallest unit of testing. It checks for a specific response to a particular set of inputs. 测试用例是最小的测试单元。它检查对特定输入集的特定响应。 |
| 160 | +> |
| 161 | +> A test suite is a collection of test cases, test suites, or both. It is used to aggregate tests taht should be executed together. 测试套件是测试用例、测试套件或两者的集合。它用于聚合应该一起执行的测试。 |
| 162 | +> |
| 163 | +> A test runner is a component thich orchestrates the execution of tests and provides the outcome to the user. 测试运行器是一个组件,它协调测试的执行并向用户提供结果。 |
| 164 | +
|
| 165 | +###### 应用Test Suite 和Test Runner 运行自动化脚本 |
| 166 | + |
| 167 | +```python |
| 168 | +import unittestdemo |
| 169 | +import unittest |
| 170 | + |
| 171 | + |
| 172 | +# 以一个类的维度去执行 |
| 173 | +cases = unittest.TestLoader.loadTestsFromTestCase(unittestdemo.MyTestCase) |
| 174 | +# 可以一次添加多个cases |
| 175 | +my_suite = unittest.TestSuite([cases]) |
| 176 | + |
| 177 | +# 添加单个测试用例,在使用ddt后,将会不可用 |
| 178 | +# my_suite = unittest.TestSuite() |
| 179 | +# my_suite.addTest(unittestdemo.MyTestCase("test_something")) |
| 180 | + |
| 181 | +my_runner = unittest.TextTestRunner(verbosity=2) |
| 182 | +my_runner.run(my_suite) |
| 183 | +``` |
| 184 | + |
| 185 | +##### 数据驱动DDT |
| 186 | + |
| 187 | +[官网](https://pypi.org/project/ddt/) |
| 188 | + |
| 189 | +> DDT(Data-Driven Tests) allows you to multiply one test case by runing it with different test data, and make it appear as multiple test cases. |
| 190 | +> |
| 191 | +> DDT(数据驱动测试)允许您将一个测试用例与不同的测试数据一起运行,从而使它显示为多个测试用例。 |
| 192 | +
|
| 193 | +###### 数据驱动DDT的使用 |
| 194 | + |
| 195 | +- 准备第三方库 |
| 196 | + |
| 197 | + > 首先安装ddt库, 其次在脚本中引入ddt |
| 198 | +
|
| 199 | +- 使用 |
| 200 | + |
| 201 | + ```python |
| 202 | + import unittest |
| 203 | + from ddt import ddt, data, unpack |
| 204 | + |
| 205 | + # 声明该测试类采用ddt |
| 206 | + @ddt |
| 207 | + class MyTestCase(unittest.TestCase): |
| 208 | + |
| 209 | + # 使用元祖存放被测试的数据,一次只有一个参数的情况,每一组数据都会执行一次测试用例 |
| 210 | + @data(1, 2, 3) |
| 211 | + def test_something(self, value): |
| 212 | + print value |
| 213 | + self.assertEqual(value, 2) |
| 214 | + |
| 215 | + # 使用元祖存放被测试的数据,一次有多个参数的情况,每一组数据都会执行一次测试用例 |
| 216 | + @data((1, 2), (2, 3)) |
| 217 | + @unpack |
| 218 | + def test_something(self, value1, value2): |
| 219 | + print value1, value2 |
| 220 | + self.assertEqual(value2, value1 + 1) |
| 221 | + |
| 222 | + if __name__ == '__main__': |
| 223 | + unittest.main() |
| 224 | + |
| 225 | + ``` |
| 226 | + |
| 227 | +- 用ddt改写测试系统计算器的测试脚本 |
| 228 | + |
| 229 | + ```python |
| 230 | + import unittest |
| 231 | + from appium import webdriver |
| 232 | + from ddt import ddt, data, unpack |
| 233 | + |
| 234 | + |
| 235 | + @ddt |
| 236 | + class MyTestCase(unittest.TestCase): |
| 237 | + |
| 238 | + def setUp(self): |
| 239 | + desired_caps = {'platformName': 'Android', 'platformVersion': '9.0', 'deviceName': '192.168.115.101:5555', |
| 240 | + 'appPackage': 'com.android.calculator2', 'appActivity': '.Calculator', |
| 241 | + "unicodeKeyboard": "True", "resetKeyboard": "True"} |
| 242 | + self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps) |
| 243 | + |
| 244 | + @data("30,352", "35,023", "12,345", "32,053") |
| 245 | + def test_something(self, expected_result): |
| 246 | + self.driver.find_element_by_id("digit_1").click() |
| 247 | + self.driver.find_element_by_id("digit_3").click() |
| 248 | + self.driver.find_element_by_id("digit_5").click() |
| 249 | + self.driver.find_element_by_id("op_add").click() |
| 250 | + self.driver.find_element_by_id("digit_8").click() |
| 251 | + self.driver.find_element_by_id("digit_9").click() |
| 252 | + self.driver.find_element_by_id("op_mul").click() |
| 253 | + self.driver.find_element_by_id("digit_3").click() |
| 254 | + self.driver.find_element_by_id("digit_9").click() |
| 255 | + self.driver.find_element_by_id("digit_2").click() |
| 256 | + self.driver.find_element_by_id("eq").click() |
| 257 | + |
| 258 | + result = self.driver.find_element_by_id("result").text |
| 259 | + self.assertEqual(result, expected_result) |
| 260 | + |
| 261 | + def tearDown(self): |
| 262 | + # 一定记得退出driver,不然下次运行会直接报错,除非在Appium中手动停止连接 |
| 263 | + self.driver.quit() |
| 264 | + |
| 265 | + |
| 266 | + if __name__ == '__main__': |
| 267 | + unittest.main() |
| 268 | + |
| 269 | + ``` |
| 270 | + |
| 271 | + |
0 commit comments