selenium POM基于unittest 自动化测试
selenium POM基于unittest 测试框架说明
1、自动化框架
由一个或多个自动化测试基础模块、自动化测试管理模块、自动化测试统计模块等组成的工具集合。
2、根据不同的分类可以分为
按框架的定义分:基础功能测试框架、管理执行框架
按不同的测试类型来分:功能自动化测试框架、性能自动化测试框架
按测试阶段分:单元自动化测试框架、接口自动化测试框架、系统自动化测试框架
按组成结构分:单一自动化测试框架、综合自动化测试框架
按部署方式分:单机自动化测试框架、分布式自动化测试框架
3、自动化框架的原则:
测试框架脚本与业务、数据分离
测试框架与被测试应用程序独立
测试框架脚本应易于扩展、维护
测试脚本所使用语言应该与框架独立
测试框架不应该让框架的复杂性影响到测试人员
4、进入主题介绍selenium POM基于unittest 测试框架说明
1.第三方包功能重新封装
2.界面元素与测试内部对象名分离
3.脚本与数据分离
4.通过Jenkins持续从svn中获取测试用例,进行持续化集成
5、总体目录结构以及说明

1.1 conf 目录: 存放的是配置文件
1.2 data目录:存放Excel的文件,参数多少可以使用Excel参数存放和读取参数以及对于的值
1.3 public包:存放的封装的工具类
1.4 report :测试报告
1.5 testcase : 存放的是测试用例
1.6 run_all.py : 运行入口
2、各模块介绍:
2.1 配置文件
如果我们程序没有任何配置文件时,这样的程序对外是全封闭的,一旦程序需要修改一些参数必须要修改程序代码本身并重新编译,这样很不好,所以要用配置文件,让程序在不同的操作系统以及环境中根据本地实际情况正常运行;配置文件有很多如INI配置文件,XML配置文件等。
conf 目录: 存放的是配置文件 conf,ini
1 [log] 2 # 日志路径 3 log_path = C:\Users\Administrator\PycharmProjects\auto_ui_test\report\log\ 4 5 [image] 6 # 截图文件路径 7 img_path = C:\Users\Administrator\PycharmProjects\auto_ui_test\report\image\ 8 9 [report] 10 # 测试报告路径 11 report_path = C:\Users\Administrator\PycharmProjects\auto_ui_test\report\ 12 13 [test_case] 14 test_case_path = C:\Users\Administrator\PycharmProjects\auto_ui_test\testcase 15 16 [data] 17 # 测试数据路径 18 data_path = C:\Users\Administrator\PycharmProjects\auto_ui_test\data
2.2 数据文件
当我们的测试用例中需要填写很多参数时,为了方便修改以及读取,参数化就应运而生。使用参数,当我们后期维护测试用例时,可以减少必要的冗余,减少后期的维护量。
data目录:存放Excel的文件,参数多少可以使用Excel参数存放和读取参数以及对于的值
这个结合本地的项目自行选择
2.3 工具类的封装
首先要说明POM(PageObjectModel)的好处
POM是Selenium中的一种测试设计模式,主要是将每一个页面设计为一个Class,其中包含页面中需要测试的元素(按钮,输入框,标题 等),这样在Selenium测试页面中可以通过调用页面类来获取页面元素,这样巧妙的避免了当页面元素id或者位置变化时,需要改测试页面代码的情况。 当页面元素id变化时,只需要更改测试页Class中页面的属性即可。
base:
存放页面上的元素以及业务流程,业务流程比较复杂也可以单独重新封装业务流程,根据本地项目自行选择
login_page.py
1 from public.common.base_obj import base_frame 2 3 4 # 页面对象(PO) 登录页面 5 class LoginPage(base_frame): 6 7 8 username_loc = ('id=userName') 9 passwd_loc = ('id=password') 10 btn_loc = ('id=login-btn') 11 error_text_loc = ('class=font-16') 12 13 14 def username(self, text): 15 self.send_keys(self.username_loc, text) 16 17 def password(self, text): 18 self.send_keys(self.passwd_loc, text) 19 20 def click_login_btn(self): 21 self.click(self.btn_loc) 22 23 def error_text(self): 24 self.get_text(self.error_text_loc) 25 26 def pro(self, username, passwd): 27 self.username(username) 28 self.password(passwd) 29 self.click_login_btn()
common:
存放的工具类, 读取配置,获取Excel,发送邮件,读取数据库,封装的selenium的api等
base_obj.py selenium的二次封装
1 # coding=utf-8 2 3 import time,os 4 from selenium import webdriver 5 from selenium.webdriver.common.action_chains import ActionChains 6 from selenium.common.exceptions import TimeoutException 7 from selenium.webdriver.support import expected_conditions as EC 8 from selenium.webdriver.support.ui import WebDriverWait 9 from selenium.webdriver.common.by import By 10 11 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) 12 conf_path = BASE_DIR + '/config/config.ini' 13 conf_path = conf_path.replace('/', '\\') 14 15 from public.common.get_log import Log 16 from public.common.get_config import r_config 17 from selenium.webdriver.common.keys import Keys 18 19 img_path = r_config(conf_path, 'image', 'img_path') 20 log_path = r_config(conf_path, 'log', 'log_path') 21 success = "SUCCESS " 22 fail = "FAIL " 23 logger = Log(log_path) 24 25 class base_frame(object): 26 27 28 def __init__(self, driver, base_url="http://www.baidu.com"): 29 self.driver = driver 30 self.base_url = base_url 31 self.timeout = 30 32 33 def my_print(self, msg): 34 logger.info(msg) 35 36 def open(self, url): 37 38 t1 = time.time() 39 try: 40 self.driver.get(url) 41 self.my_print("{0} Navigated to {1}, Spend {2} seconds".format(success, url, time.time() - t1)) 42 except Exception: 43 self.my_print("{0} Unable to load {1}, Spend {2} seconds".format(fail, url, time.time() - t1)) 44 raise 45 46 def max_window(self): 47 48 t1 = time.time() 49 self.driver.maximize_window() 50 self.my_print("{0} Set browser window maximized, Spend {1} seconds".format(success, time.time() - t1)) 51 52 def set_window(self, wide, high): 53 54 t1 = time.time() 55 self.driver.set_window_size(wide, high) 56 self.my_print("{0} Set browser window wide: {1},high: {2}, Spend {3} seconds".format(success, 57 wide, high, 58 time.time() - t1)) 59 60 def wait(self, secs): 61 62 t1 = time.time() 63 self.driver.implicitly_wait(secs) 64 self.my_print("{0} Set wait all element display in {1} seconds, Spend {2} seconds".format(success, 65 secs, 66 time.time() - t1)) 67 68 def find_element(self, element): 69 70 if "=" not in element: 71 raise NameError("Positioning syntax errors, lack of '='") 72 73 by = element[:element.index("=")] 74 value = element[element.index("=")+1:] 75 76 if by == "id": 77 return self.driver.find_element_by_id(value) 78 elif by == "name": 79 return self.driver.find_element_by_name(value) 80 elif by == "class": 81 return self.driver.find_element_by_class_name(value) 82 elif by == "text": 83 return self.driver.find_element_by_link_text(value) 84 elif by == "text_part": 85 return self.driver.find_element_by_partial_link_text(value) 86 elif by == "xpath": 87 return self.driver.find_element_by_xpath(value) 88 elif by == "css": 89 return self.driver.find_element_by_css_selector(value) 90 else: 91 raise NameError("Please enter the correct targeting elements,'id','name','class','text','xpath','css'.") 92 93 def wait_element(self, element, seconds=5): 94 95 96 if "=" not in element: 97 raise NameError("Positioning syntax errors, lack of '='") 98 99 by = element[:element.index("=")] 100 value = element[element.index("=")+1:] 101 messages = 'Element: {0} not found in {1} seconds.'.format(element, seconds) 102 103 if by == "id": 104 WebDriverWait(self.driver, seconds, 1).until(EC.presence_of_element_located((By.ID, value)), messages) 105 elif by == "name": 106 WebDriverWait(self.driver, seconds, 1).until(EC.presence_of_element_located((By.NAME, value)), messages) 107 elif by == "class": 108 WebDriverWait(self.driver, seconds, 1).until(EC.presence_of_element_located((By.CLASS_NAME, value)), 109 messages) 110 elif by == "text": 111 WebDriverWait(self.driver, seconds, 1).until(EC.presence_of_element_located((By.LINK_TEXT, value)), 112 messages) 113 elif by == "xpath": 114 WebDriverWait(self.driver, seconds, 1).until(EC.presence_of_element_located((By.XPATH, value)), messages) 115 elif by == "css": 116 WebDriverWait(self.driver, seconds, 1).until(EC.presence_of_element_located((By.CSS_SELECTOR, value)), 117 messages) 118 else: 119 raise NameError("Please enter the correct targeting elements,'id','name','class','text','xpaht','css'.") 120 121 def send_keys(self, element, text): 122 123 t1 = time.time() 124 try: 125 self.wait_element(element) 126 self.find_element(element).clear() 127 self.find_element(element).send_keys(text) 128 self.my_print("{0} Typed element: <{1}> content: {2}, Spend {3} seconds".format(success, 129 element, text, 130 time.time() - t1)) 131 except Exception: 132 self.my_print("{0} Unable to type element: <{1}> content: {2}, Spend {3} seconds".format(fail, 133 element, text, 134 time.time() - t1)) 135 raise 136 137 def send_keys_and_enter(self, element, text, secs=0.5): 138 139 t1 = time.time() 140 try: 141 self.wait_element(element) 142 self.find_element(element).clear() 143 self.find_element(element).send_keys(text) 144 time.sleep(secs) 145 self.find_element(element).send_keys(Keys.ENTER) 146 self.my_print( 147 "{0} Element <{1}> type content: {2},and sleep {3} seconds,input ENTER key, Spend {4} seconds".format( 148 success, element, text, secs, time.time() - t1)) 149 except Exception: 150 self.my_print( 151 "{0} Unable element <{1}> type content: {2},and sleep {3} seconds,input ENTER key, Spend {4} seconds". 152 format(fail, element, text, secs, time.time() - t1)) 153 raise 154 155 def click(self, element): 156 157 t1 = time.time() 158 try: 159 self.wait_element(element) 160 self.find_element(element).click() 161 self.my_print("{0} Clicked element: <{1}>, Spend {2} seconds".format(success, element, time.time() - t1)) 162 except Exception: 163 self.my_print( 164 "{0} Unable to click element: <{1}>, Spend {2} seconds".format(fail, element, time.time() - t1)) 165 raise 166 167 def right_click(self, element): 168 169 t1 = time.time() 170 try: 171 self.wait_element(element) 172 ActionChains(self.driver).context_click(self.find_element(element)).perform() 173 self.my_print( 174 "{0} Right click element: <{1}>, Spend {2} seconds".format(success, element, time.time() - t1)) 175 except Exception: 176 self.my_print( 177 "{0} Unable to right click element: <{1}>, Spend {2} seconds".format(fail, element, time.time() - t1)) 178 raise 179 180 def move_to_element(self, element): 181 182 t1 = time.time() 183 try: 184 self.wait_element(element) 185 ActionChains(self.driver).move_to_element(self.find_element(element)).perform() 186 self.my_print("{0} Move to element: <{1}>, Spend {2} seconds".format(success, element, time.time() - t1)) 187 except Exception: 188 self.my_print( 189 "{0} unable move to element: <{1}>, Spend {2} seconds".format(fail, element, time.time() - t1)) 190 raise 191 192 def double_click(self, element): 193 194 t1 = time.time() 195 try: 196 self.wait_element(element) 197 ActionChains(self.driver).double_click(self.find_element(element)).perform() 198 self.my_print( 199 "{0} Double click element: <{1}>, Spend {2} seconds".format(success, element, time.time() - t1)) 200 except Exception: 201 self.my_print( 202 "{0} Unable to double click element: <{1}>, Spend {2} seconds".format(fail, element, time.time() - t1)) 203 raise 204 205 def drag_and_drop(self, source_element, target_element): 206 207 t1 = time.time() 208 try: 209 self.wait_element(source_element) 210 self.wait_element(target_element) 211 ActionChains(self.driver).drag_and_drop(self.find_element(source_element), 212 self.find_element(target_element)).perform() 213 self.my_print("{0} Drag and drop element: <{1}> to element: <{2}>, Spend {3} seconds".format(success, 214 source_element, 215 target_element, 216 time.time() - t1)) 217 except Exception: 218 self.my_print("{0} Unable to drag and drop element: <{1}> to element: <{2}>, Spend {3} seconds".format(fail, 219 source_element, 220 target_element, 221 time.time() - t1)) 222 raise 223 224 def back(self): 225 226 t1 = time.time() 227 self.driver.back() 228 self.my_print("{0} Back to old window, Spend {1} seconds".format(success, time.time() - t1)) 229 230 def forward(self): 231 232 t1 = time.time() 233 self.driver.forward() 234 self.my_print("{0} Forward to old window, Spend {1} seconds".format(success, time.time() - t1)) 235 236 def get_attribute_on(self, element, attribute): 237 238 t1 = time.time() 239 try: 240 self.wait_element(element) 241 attr = self.find_element(element).get_attribute(attribute) 242 self.my_print("{0} Get attribute element: <{1}>,attribute: {2}, Spend {3} seconds".format(success, 243 element, 244 attribute, 245 time.time() - t1)) 246 return attr 247 except Exception: 248 self.my_print("{0} Unable to get attribute element: <{1}>,attribute: {2}, Spend {3} seconds".format(fail, 249 element, 250 attribute, 251 time.time() - t1)) 252 raise 253 254 def get_text(self, element): 255 256 t1 = time.time() 257 258 try: 259 self.wait_element(element) 260 text = self.find_element(element).text 261 self.my_print( 262 "{0} Get element text element: <{1}>, Spend {2} seconds".format(success, element, time.time() - t1)) 263 return text 264 except Exception: 265 self.my_print( 266 "{0} Unable to get element text element: <{1}>, Spend {2} seconds".format(fail, element, 267 time.time() - t1)) 268 raise 269 270 def get_display(self, element): 271 272 t1 = time.time() 273 try: 274 self.wait_element(element) 275 self.find_element(element).is_displayed() 276 self.my_print("{0} the element is display, Spend {1} seconds".format(success, time.time() - t1)) 277 return True 278 except Exception: 279 self.my_print("{0} the element is not display, Spend {1} seconds".format(fail, time.time() - t1)) 280 return False 281 282 def get_title(self): 283 284 t1 = time.time() 285 title = self.driver.title 286 self.my_print("{0} Get current window title, Spend {1} seconds".format(success, time.time() - t1)) 287 return title 288 289 def get_url(self): 290 291 t1 = time.time() 292 url = self.driver.current_url 293 self.my_print("{0} Get current window url, Spend {1} seconds".format(success, time.time() - t1)) 294 return url 295 296 def get_screenshot(self, file_name): 297 298 t1 = time.time() 299 try: 300 file_path = img_path + file_name 301 self.driver.get_screenshot_as_file(file_path) 302 self.my_print("{0} Get the current window screenshot,path: {1}, Spend {2} seconds".format(success, 303 file_path, 304 time.time() - t1)) 305 except Exception: 306 self.my_print("{0} Unable to get the current window screenshot,path: {1}, Spend {2} seconds".format(fail, 307 file_path, 308 time.time() - t1)) 309 raise 310 311 def submit(self, element): 312 313 t1 = time.time() 314 try: 315 self.wait_element(element) 316 self.find_element(element).submit() 317 self.my_print( 318 "{0} Submit form args element: <{1}>, Spend {2} seconds".format(success, element, time.time() - t1)) 319 except Exception: 320 self.my_print( 321 "{0} Unable to submit form args element: <{1}>, Spend {2} seconds".format(fail, element, 322 time.time() - t1)) 323 raise 324 325 def switch_to_frame(self, element): 326 327 t1 = time.time() 328 try: 329 self.wait_element(element) 330 self.driver.switch_to.frame(self.find_element(element)) 331 332 self.my_print( 333 "{0} Switch to frame element: <{1}>, Spend {2} seconds".format(success, element, time.time() - t1)) 334 except Exception: 335 self.my_print( 336 "{0} Unable switch to frame element: <{1}>, Spend {2} seconds".format(fail, element, time.time() - t1)) 337 raise 338 339 def switch_to_frame_out(self): 340 341 t1 = time.time() 342 self.driver.switch_to.default_content() 343 self.my_print("{0} Switch to frame out, Spend {1} seconds".format(success, time.time() - t1)) 344 345 def switch_new_window(self, element): 346 347 t1 = time.time() 348 try: 349 current_windows = self.driver.current_window_handle 350 self.find_element(element).click() 351 all_handles = self.driver.window_handles 352 for handle in all_handles: 353 if handle != current_windows: 354 self.driver.switch_to.window(handle) 355 self.my_print("{0} Click element: <{1}> open a new window and swich into, Spend {2} seconds".format(success, 356 element, 357 time.time() - t1)) 358 except Exception: 359 self.my_print("{0} Click element: <{1}> open a new window and swich into, Spend {2} seconds".format(fail, 360 element, 361 time.time() - t1)) 362 raise 363 364 def into_new_window(self): 365 366 t1 = time.time() 367 try: 368 all_handle = self.driver.window_handles 369 flag = 0 370 while len(all_handle) < 2: 371 time.sleep(1) 372 all_handle = self.driver.window_handles 373 flag += 1 374 if flag == 5: 375 break 376 self.driver.switch_to.window(all_handle[-1]) 377 self.my_print("{0} Switch to the new window,new window's url: {1}, Spend {2} seconds".format(success, 378 self.driver.current_url, 379 time.time() - t1)) 380 except Exception: 381 self.my_print("{0} Unable switch to the new window, Spend {1} seconds".format(fail, time.time() - t1)) 382 raise 383 384 def F5(self): 385 386 t1 = time 387 self.driver.refresh() 388 self.my_print("{0} Refresh the current page, Spend {1} seconds".format(success, time.time() - t1)) 389 390 def js(self, script): 391 392 t1 = time.time() 393 394 try: 395 self.driver.execute_script(script) 396 self.my_print( 397 "{0} Execute javascript scripts: {1}, Spend {2} seconds".format(success, script, time.time() - t1)) 398 except Exception: 399 self.my_print("{0} Unable to execute javascript scripts: {1}, Spend {2} seconds".format(fail, 400 script, 401 time.time() - t1)) 402 raise 403 404 def accept_alert(self): 405 406 t1 = time.time() 407 408 self.driver.switch_to.alert.accept() 409 self.my_print("{0} Accept warning box, Spend {1} seconds".format(success, time.time() - t1)) 410 411 def dismiss_alert(self): 412 413 t1 = time.time() 414 self.driver.switch_to.alert.dismiss() 415 self.my_print("{0} Dismisses the alert available, Spend {1} seconds".format(success, time.time() - t1)) 416 417 def close(self): 418 419 t1 = time.time() 420 self.driver.close() 421 self.my_print("{0} Closed current window, Spend {1} seconds".format(success, time.time() - t1)) 422 423 def quit(self): 424 425 t1 = time.time() 426 self.driver.quit() 427 self.my_print("{0} Closed all window and quit the driver, Spend {1} seconds".format(success, time.time() - t1)) 428 429 def element_exist(self, element): 430 431 t1 = time.time() 432 try: 433 self.wait_element(element) 434 self.my_print("{0} Element: <{1}> is exist, Spend {2} seconds".format(success, element, time.time() - t1)) 435 return True 436 except TimeoutException: 437 self.my_print("{0} Element: <{1}> is not exist, Spend {2} seconds".format(fail, element, time.time() - t1)) 438 return False 439 440 @property 441 def origin_driver(self): 442 443 return self.driver 444 445 def js_click(self, element): 446 447 t1 = time.time() 448 js_str = "$('{0}').click()".format(element) 449 try: 450 self.driver.execute_script(js_str) 451 self.my_print( 452 "{0} Use javascript click element: {1}, Spend {2} seconds".format(success, js_str, time.time() - t1)) 453 except Exception: 454 self.my_print("{0} Unable to use javascript click element: {1}, Spend {2} seconds".format(fail, 455 js_str, 456 time.time() - t1)) 457 raise 458 459 460 461 462 463 464 if __name__ == '__main__': 465 dr = base_frame() 466 dr.open('http://www.baidu.com') 467 dr.max_window() 468 dr.find_element('id=kw') 469 dr.get_screenshot('1.jpg') 470 dr.close()
get_config.py 获取配置文件
1 import configparser 2 import os 3 import sys 4 5 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) 6 conf_dir = BASE_DIR + '/config/config.ini' 7 conf_dir = conf_dir.replace('/', '\\') 8 9 class Config(object): 10 11 def __init__(self, path): 12 self.path = path 13 self.cf = configparser.ConfigParser() 14 self.cf.read(self.path, encoding='utf-8') 15 16 def get(self, field, key): 17 result = "" 18 try: 19 result = self.cf.get(field, key) 20 except: 21 result = "" 22 return result 23 24 def set(self, field, key, value): 25 try: 26 self.cf.set(field, key, value) 27 self.cf.write(open(self.path, 'w')) 28 except: 29 return False 30 return True 31 32 33 def r_config(config_file_path, field, key): 34 rf = configparser.ConfigParser() 35 try: 36 rf.read(config_file_path, encoding='utf-8') 37 result = rf.get(field, key) 38 except: 39 sys.exit(1) 40 return result 41 42 43 def w_config(config_file_path, field, key, value): 44 wf = configparser.ConfigParser() 45 try: 46 wf.read(config_file_path) 47 wf.set(field, key, value) 48 wf.write(open(config_file_path, 'w')) 49 except: 50 sys.exit(1) 51 return True 52 53 54 55 56 57 if __name__ == '__main__': 58 59 60 b = r_config(conf_dir, 'image', 'img_path') 61 print(b)
get_db.py 连接数据库
1 import configparser 2 import os 3 import sys 4 5 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) 6 conf_dir = BASE_DIR + '/config/config.ini' 7 conf_dir = conf_dir.replace('/', '\\')
get_excel.py 获取Excel
1 import configparser 2 import os 3 import sys 4 5 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) 6 conf_dir = BASE_DIR + '/config/config.ini' 7 conf_dir = conf_dir.replace('/', '\\')
get_files.py 获取测试报告
1 import os, sys 2 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 3 sys.path.append(BASE_DIR) 4 5 6 # 查找最新生成的测试报告 7 def get_new_file(files): 8 lists = os.listdir(files) 9 lists.sort(key=lambda fn: os.path.getmtime(files+fn)) 10 file_ = os.path.join(files, lists[-1]) 11 print(file_) 12 return file_
get_images.py 获取截图
1 import os 2 from public.common.get_config import r_config 3 from selenium.webdriver import Remote 4 from selenium import webdriver 5 6 7 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) 8 conf_path = BASE_DIR + '/config/config.ini' 9 conf_path = conf_path.replace('/', '\\') 10 img_path = r_config(conf_path, "image", "img_path") 11 print(img_path) 12 13 14 15 def insert_img(driver, file_name): 16 driver.get_screenshot_as_file(file_name) 17 18 19 20 # 启动浏览器驱动 21 def browser(): 22 driver = webdriver.Chrome() 23 ''' 24 host = '127.0.0.1:4444' # 运行主机:端口号 (本机默认:127.0.0.1:4444) 25 dc = {'browserName': 'chrome'} # 指定浏览器('chrome','firefox',) 26 driver = Remote(command_executor='http://' + host + '/wd/hub', 27 desired_capabilities=dc) 28 ''' 29 return driver 30 31 32 33 34 35 36 if __name__ == '__main__': 37 driver = webdriver.Chrome() 38 driver.get("https://www.baidu.com") 39 insert_img('123') 40 driver.quit()
get_log.py 获取日志
1 # coding=utf-8 2 3 import os, sys, time, logging 4 from public.common.get_config import r_config 5 6 7 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) 8 conf_path = BASE_DIR + '/config/config.ini' 9 conf_path = conf_path.replace('/', '\\') 10 log_path = r_config(conf_path, "log", "log_path") 11 12 13 class Log(): 14 15 def __init__(self, conf_path): 16 self.logname = os.path.join(log_path, '{0}.log'.format(time.strftime('%Y-%m-%d'))) 17 18 def __printconsole(self, level, message): 19 # 创建一个logger 20 logger = logging.getLogger() 21 logger.setLevel(logging.DEBUG) 22 # 创建一个handler,用于写入日志文件 23 fh = logging.FileHandler(self.logname,'a',encoding='utf-8') 24 fh.setLevel(logging.DEBUG) 25 # 再创建一个handler,用于输出到控制台 26 ch = logging.StreamHandler() 27 ch.setLevel(logging.DEBUG) 28 # 定义handler的输出格式 29 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 30 fh.setFormatter(formatter) 31 ch.setFormatter(formatter) 32 # 给logger添加handler 33 logger.addHandler(fh) 34 logger.addHandler(ch) 35 # 记录一条日志 36 if level == 'info': 37 logger.info(message) 38 elif level == 'debug': 39 logger.debug(message) 40 elif level == 'warning': 41 logger.warning(message) 42 elif level == 'error': 43 logger.error(message) 44 logger.removeHandler(ch) 45 logger.removeHandler(fh) 46 # 关闭打开的文件 47 fh.close() 48 49 def debug(self, message): 50 self.__printconsole('debug', message) 51 52 def info(self, message): 53 self.__printconsole('info', message) 54 55 def warning(self, message): 56 self.__printconsole('warning', message) 57 58 def error(self, message): 59 self.__printconsole('error', message) 60 61 62 if __name__ == '__main__': 63 64 Log(conf_path)
my_unit.py unittest开始和结束,净化测试环境
1 import os 2 import unittest 3 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) 4 conf_path = BASE_DIR + '/config/config.ini' 5 conf_path = conf_path.replace('/', '\\') 6 from public.common.get_config import r_config 7 from public.common.get_log import Log 8 from public.common.get_images import browser, insert_img 9 10 img_path = r_config(conf_path, 'image', 'img_path') 11 12 class MyTest(unittest.TestCase): 13 14 global case_count 15 case_count = 0 16 17 global image_count 18 image_count = 0 19 20 # 计算测试用例的个数,用于显示在测试报告中 21 def case_id(self): 22 global case_count 23 case_count += 1 24 if case_count <= 9: 25 count = "00" + str(case_count) 26 elif case_count <= 99: 27 count = "0" + str(case_count) 28 else: 29 count = str(case_count) 30 return count 31 32 # 测试完成,生成截图文件的名称 33 def image_id(self): 34 global image_count 35 image_count += 1 36 if image_count <= 9: 37 count = "00" + str(image_count) 38 elif image_count <= 99: 39 count = "0" + str(image_count) 40 else: 41 count = str(image_count) 42 return count 43 44 def setUp(self): 45 self.logger = Log(os.path.join(os.path.dirname(os.path.dirname(os.getcwd())), 'conf/conf.ini')) 46 self.logger.info('############################### START ###############################') 47 self.driver = browser() 48 self.driver.implicitly_wait(10) 49 self.driver.maximize_window() 50 print("case " + str(self.case_id())) 51 52 def tearDown(self): 53 img_id = self.image_id() 54 file_name =img_path + img_id + ".jpg" 55 print(file_name) 56 insert_img(self.driver, file_name) 57 self.driver.quit() 58 self.logger.info('############################### End ###############################')
send_email.py 获取配置文件
1 from email.mime.text import MIMEText 2 from email.utils import formataddr 3 import smtplib, os, sys 4 BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) 5 sys.path.append(BASE_DIR) 6 7 8 9 def send_mail(file_new): 10 11 mail_from = 'XX@XX.com' 12 mail_to = 'XX@XX.com' 13 f = open(file_new, 'rb') 14 mail_body = f.read() 15 f.close() 16 17 msg = MIMEText(mail_body, _subtype='html', _charset='utf-8') 18 msg['From'] = formataddr(["XX", mail_from]) 19 msg['To'] = formataddr(["XX", mail_to]) 20 msg['Subject'] = u"自动化测试报告" 21 smtp = smtplib.SMTP('smtp.exmail.qq.com', '25') 22 smtp.login('XX@XX.com', 'XX%') 23 smtp.sendmail(mail_from, mail_to, msg.as_string()) 24 smtp.quit() 25 print('email has send out !')
pakeage:
存放第三方的包,浏览器的驱动等
HTMLTestRunner3.py
2.3 测试报告以及日志
存放测试报告以及日志
image:存放测试截图
log:存放的日志文件
report: 存放测试报告
2.4 testcase
存放测试用例,测试用例需要以 test 开头
login_case.py
1 from time import sleep 2 import unittest, random, sys, os 3 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 4 conf = BASE_DIR + '/config/config.ini' 5 6 public = base = BASE_DIR + '/public' 7 common = BASE_DIR + '/public/common' 8 base = BASE_DIR + '/public/base' 9 10 conf_path = conf.replace('/', '\\') 11 public_path = public.replace('/', '\\') 12 common_path = common.replace('/', '\\') 13 base_path = base.replace('/', '\\') 14 15 sys.path.append(conf_path) 16 sys.path.append(public_path) 17 sys.path.append(base_path) 18 sys.path.append(common_path) 19 20 from public.common import my_unit 21 from public.base.login_page import LoginPage 22 23 24 25 26 class loginTest(my_unit.MyTest): 27 '''社区登录测试''' 28 29 def test_login_user_pawd_null(self): 30 '''用户名、密码为空登录''' 31 po = LoginPage(self.driver) 32 po.open('http://192.168.20.12:8080/nisdn_platform/') 33 username = "" 34 passwd = "" 35 po.pro(username, passwd) 36 sleep(2) 37 self.assertEqual(po.error_text(), '用户名不能为空!') 38 39 def test_login_pawd_null(self): 40 '''密码为空登录''' 41 po = LoginPage(self.driver) 42 po.open('http://192.168.20.12:8080/nisdn_platform/') 43 username = "admin" 44 passwd = "" 45 po.pro(username, passwd) 46 sleep(2) 47 self.assertEqual(po.error_text(), '密码不能为空!') 48 49 def test_login_user_pawd_error(self): 50 '''用户名、密码为错误''' 51 po = LoginPage(self.driver) 52 po.open('http://192.168.20.12:8080/nisdn_platform/') 53 character = random.choice('zyxwvutsrqponmlkjihgfedcba') 54 username = "admin" + character 55 passwd = "admin" 56 po.pro(username, passwd) 57 sleep(2) 58 self.assertEqual(po.error_text(), '用户名只能输入字母或者数字!!') 59 60 def test_login_success(self): 61 '''用户名、密码正确,登录成功''' 62 po = LoginPage(self.driver) 63 po.open('http://192.168.20.12:8080/nisdn_platform/') 64 user = "admin" 65 passwd = "admin" 66 po.pro(user, passwd) 67 sleep(2) 68 69 70 71 if __name__ == '__main__': 72 #unittest.main() 73 suit = unittest.TestSuite() 74 suit.addTest(loginTest("test_login_success")) 75 runner = unittest.TextTestRunner() 76 runner.run(suit)
2.5 run_all.py
程序的入口
1 import os, sys, time, unittest 2 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) 3 conf = BASE_DIR + '/config/config.ini' 4 public = base = BASE_DIR + '/public' 5 common = BASE_DIR + '/public/common' 6 base = BASE_DIR + '/public/base' 7 conf_path = conf.replace('/', '\\') 8 public_path = public.replace('/', '\\') 9 common_path = common.replace('/', '\\') 10 base_path = base.replace('/', '\\') 11 sys.path.append(conf_path) 12 sys.path.append(public_path) 13 sys.path.append(base_path) 14 sys.path.append(common_path) 15 from public.common.send_email import send_mail 16 from public.pakeage.HTMLTestRunner3 import HTMLTestRunner 17 from public.common.get_config import r_config 18 from public.common.get_files import get_new_file 19 20 img_path = r_config(conf_path, 'image', 'img_path') 21 log_path = r_config(conf_path, 'log', 'log_path') 22 report_path = r_config(conf_path, 'report', 'report_path') 23 test_case_path = r_config(conf_path, 'test_case', 'test_case_path') 24 25 26 if __name__ == '__main__': 27 now_time = time.strftime("%Y-%m-%d-%H-%M-%S") 28 fp = open(report_path + now_time + "_result.html", 'wb') 29 runner = HTMLTestRunner(fp, title="网易邮箱测试报告", description="运行环境:macOS Sierra, chrome") 30 discover = unittest.defaultTestLoader.discover(test_case_path, pattern='login_*.py') 31 runner.run(discover) 32 fp.close() 33 file_path = get_new_file(report_path) 34 send_mail(file_path)
3、程序源码
浙公网安备 33010602011771号