TestComplete---Object Manage对象管理

本文详细介绍了TestComplete对象管理中的Name Mapping、Aliases、Object Spy、Region方式、OCR方式和Text Recognition方式识别对象的方法及用法。

TestComplete 对象管理


作者: Max.Bai

时间: 2012/12


Object Manage

1. Name Mapping

Base mode: 通过添加的对象属性来识别对象

Conditional mode: 这个功能可以使用and, or 条件组合来设置识别对象的属性

在修改对象识别窗口点击conditional mode可以打开conditional mode,可以通过点击 and or 来组合识别条件,选中已存在条件点击and or 可以实现括号组合条件。

Name mapping template: 这个功能是添加识别对象的模板用来识别对象,当自动识别的属性不够时,可以通过手动添加属性来设置,模板可以用来批量设置对象识别属性。

2. Aliases

就是对象的别名了,可以通过拖拽对象来修改层级关系,让很长的对象名变的很短,使用起来方便

3. Object spy

对象识别工具,分两种识别方式,Drag方式(拖拽)和Point and Fix 模式(直接点击)识别,当这种方式无法识别对象是可以使用 坐标,Region, OCR Text Recognition 方式,后面会说明他们的用法。

4. Region 方式识别对象

Region Stores 里面存储图片用的,当然也可以用来识别对象,有点像QTP里面的虚拟对象。

用法步骤:

1) Stores-->regions 添加要识别的对象区域图片设置名字

2) 用Region.Find() 获得图片在主窗口的正确位置 

Var rectImage = Regions. Find(WinObj, “RegionName” )

3) 通过获得的位置来点击图片位置

WinObj.Click(rectImage.Left + rectImage.Width/2, rectImage.Top + rectImage.Height/2)

5. Optical Character Recognition (OCR)方式识别对象

OCR 方式可以通过字符来识别对象当然OCR还可以通过GetText方法获得图片上的文字。

例子代码:

' Get the tested window
Set myWnd = Sys.Process("MyProcess").Window("MyWindowClass", "My Window Caption", 1)

' Get the TextObject object
Set textObj = myWnd.TextObject("My Desired Text")

6. Text Recognition 方式识别对象

Text Recognition 有两种方式:

1) 通过设置project property -->Open applications-->Text Recognition

Project property Text Recognition 添加需要别的winclass 类型来识别,会自动给添加的类型通过Text Recognition识别相应的对象

例如:winclass SysTreeView32 的文件夹左边的树结构无法识别里面的子项, 添加SysTreeView32 到 Text Recognition list, 再次识别的时候就添加了好多TextObject 的对象在树结构下面,例如C:盘

2) 通过代码直接写

WinObj.TextObject(“text”)


# PO六层模型:用例test开头+精简代码 import unittest import time from selenium import webdriver from selenium.webdriver.edge.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import ( TimeoutException, NoSuchElementException, ElementClickInterceptedException ) # ------------------------------ 1. 配置层(Config)------------------------------ class Config: LOGIN_URL = "http://192.168.178.134:8000/admin/index.html#/login" EDGE_DRIVER_PATH = r'F:\edge\msedgedriver.exe' ADMIN_USERNAME = "admin" ADMIN_PASSWORD = "123456" WAIT_TIME = 3 # 统一等待时间 SHORT_WAIT = 1 # 短等待(仅用于元素交互间隙) # ------------------------------ 2. 基础层(BasePage)------------------------------ class BasePage: def __init__(self, driver): self.driver = driver self.driver.implicitly_wait(Config.WAIT_TIME) self.wait = WebDriverWait(self.driver, Config.WAIT_TIME) def open_url(self, url): self.driver.get(url) self.wait_for_page_load() def wait_for_page_load(self): try: self.wait.until(lambda d: d.execute_script("return document.readyState") == "complete") except TimeoutException: raise TimeoutException("页面加载超时") def click_element(self, locator): try: elem = self.wait.until(EC.element_to_be_clickable(locator)) elem.click() except ElementClickInterceptedException: self.driver.implicitly_wait(Config.SHORT_WAIT) elem = self.wait.until(EC.element_to_be_clickable(locator)) elem.click() def input_text_to_element(self, locator, text): elem = self.wait.until(EC.visibility_of_element_located(locator)) elem.clear() elem.send_keys(text) if elem.get_attribute("value") != text: raise Exception(f"输入失败:预期「{text}」,实际「{elem.get_attribute('value')}」") def select_dropdown_option(self, select_locator, option_locator): self.click_element(select_locator) self.driver.implicitly_wait(Config.SHORT_WAIT) self.click_element(option_locator) def get_element_text(self, locator): return self.wait.until(EC.visibility_of_element_located(locator)).text.strip() def is_element_displayed(self, locator): try: self.wait.until(EC.visibility_of_element_located(locator)) return True except TimeoutException: return False def handle_alert_popup(self): try: self.wait.until(EC.alert_is_present()).accept() except TimeoutException: pass # ------------------------------ 3. 页面对象层(PageLocators)------------------------------ class PageLocators: """仅保留元素定位,无任何冗余内容""" # 登录页 LOGIN_INPUT_USER = (By.XPATH, '//*[@id="app"]/div/form/div[2]/div/div[1]/input') LOGIN_INPUT_PWD = (By.XPATH, '//*[@id="app"]/div/form/div[3]/div/div/input') LOGIN_BTN_SUBMIT = (By.XPATH, '//*[@id="app"]/div/form/button') # 导航菜单 MENU_USER_MANAGE = (By.XPATH, '//*[@id="app"]/div/div[1]/div[2]/div[1]/div/ul/div[2]/li/div/span') MENU_STUDENT_LIST = (By.XPATH, '//*[@id="app"]/div/div[1]/div[2]/div[1]/div/ul/div[2]/li/ul/div[1]/a/li/span') # 学生列表页-操作按钮 STUDENT_BTN_ADD = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/form/div[2]/div/a/button/span') STUDENT_BTN_SUBMIT = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/form/div[10]/div/button[1]') STUDENT_BTN_QUERY = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/form//div/button[1]/span') STUDENT_BTN_EDIT = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/div[1]/div[3]/table/tbody/tr[1]/td[9]/div/a[1]/button/span') STUDENT_BTN_DELETE = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/div[1]/div[3]/table/tbody/tr[1]/td[9]/div/button[2]/span') STUDENT_BTN_STATUS_SWITCH = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/div[1]/div[3]/table/tbody/tr[1]/td[9]/div/button[1]/span') # 学生列表页-输入框 STUDENT_INPUT_USERNAME = (By.XPATH, '/html/body/div/div/div[2]/section/div/form/div[1]/div/div[1]/input') STUDENT_INPUT_PASSWORD = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/form/div[2]/div/div/input') STUDENT_INPUT_REAL_NAME = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/form/div[3]/div/div/input') STUDENT_INPUT_QUERY = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/form/div[1]/div/div/input') # 学生列表页-下拉选项 STUDENT_SELECT_GRADE = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/form/div[8]/div/div/div/input') STUDENT_OPTION_GRADE_1 = (By.XPATH, '/html/body/div[2]/div[1]/div[1]/ul/li[1]') STUDENT_OPTION_GRADE_2 = (By.XPATH, '/html/body/div[2]/div[1]/div[1]/ul/li[2]') # 学生列表页-验证元素 STUDENT_TEXT_FIRST_USER = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/div[1]/div[3]/table/tbody/tr[1]/td[2]/div') STUDENT_TEXT_FIRST_GRADE = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/div[1]/div[3]/table/tbody/tr[1]/td[4]/div') STUDENT_TEXT_STATUS = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/div[1]/div[3]/table/tbody/tr[1]/td[8]/div/span') STUDENT_TEXT_NO_DATA = (By.XPATH, '//*[@id="app"]/div/div[2]/section/div/div[1]/div[3]/div/span') # ------------------------------ 4. 页面操作层(PageActions)------------------------------ class LoginPageActions(BasePage): """登录页单一操作,无冗余逻辑""" def __init__(self, driver): super().__init__(driver) self.loc = PageLocators() def open_login_page(self): self.open_url(Config.LOGIN_URL) def input_login_username(self, username): self.input_text_to_element(self.loc.LOGIN_INPUT_USER, username) def input_login_password(self, password): self.input_text_to_element(self.loc.LOGIN_INPUT_PWD, password) def click_login_submit_btn(self): self.click_element(self.loc.LOGIN_BTN_SUBMIT) def is_login_success(self): return self.is_element_displayed(self.loc.MENU_USER_MANAGE) class StudentPageActions(BasePage): """学生列表页单一操作,无冗余逻辑""" def __init__(self, driver): super().__init__(driver) self.loc = PageLocators() # 导航操作 def click_user_manage_menu(self): self.click_element(self.loc.MENU_USER_MANAGE) def click_student_list_menu(self): self.click_element(self.loc.MENU_STUDENT_LIST) # 表单操作 def click_add_student_btn(self): self.click_element(self.loc.STUDENT_BTN_ADD) def input_student_username(self, username): self.driver.implicitly_wait(Config.SHORT_WAIT) self.input_text_to_element(self.loc.STUDENT_INPUT_USERNAME, username) def input_student_password(self, password): self.input_text_to_element(self.loc.STUDENT_INPUT_PASSWORD, password) def input_student_real_name(self, real_name): self.input_text_to_element(self.loc.STUDENT_INPUT_REAL_NAME, real_name) def click_student_submit_btn(self): self.click_element(self.loc.STUDENT_BTN_SUBMIT) # 下拉选择 def click_grade_select_box(self): self.click_element(self.loc.STUDENT_SELECT_GRADE) def click_grade_1_option(self): self.click_element(self.loc.STUDENT_OPTION_GRADE_1) def click_grade_2_option(self): self.click_element(self.loc.STUDENT_OPTION_GRADE_2) # 查询操作 def input_query_keyword(self, keyword): self.input_text_to_element(self.loc.STUDENT_INPUT_QUERY, keyword) def click_query_btn(self): self.click_element(self.loc.STUDENT_BTN_QUERY) # 编辑/删除/状态切换 def click_edit_student_btn(self): self.click_element(self.loc.STUDENT_BTN_EDIT) def click_delete_student_btn(self): self.click_element(self.loc.STUDENT_BTN_DELETE) def click_status_switch_btn(self): self.click_element(self.loc.STUDENT_BTN_STATUS_SWITCH) # 结果验证 def get_first_student_username(self): return self.get_element_text(self.loc.STUDENT_TEXT_FIRST_USER) def get_first_student_grade(self): return self.get_element_text(self.loc.STUDENT_TEXT_FIRST_GRADE) def get_student_status_text(self): return self.get_element_text(self.loc.STUDENT_TEXT_STATUS) def is_no_data_displayed(self): return self.is_element_displayed(self.loc.STUDENT_TEXT_NO_DATA) # ------------------------------ 5. 测试数据层(TestData)------------------------------ class TestData: """仅保留测试数据,无冗余说明""" STUDENT_INFO = { "username": "赵六", "password": "123456", "real_name": "赵遛", "target_grade_2": "二年级", "status_enabled": "启用", "status_disabled": "禁用" } LOGIN_INFO = { "username": Config.ADMIN_USERNAME, "password": Config.ADMIN_PASSWORD } # ------------------------------ 6. 用例层(TestCases)------------------------------ class TestStudentManagement(unittest.TestCase): """所有用例以test_开头,按编号命名,步骤精简""" @classmethod def setUpClass(cls): # 初始化浏览器与操作对象 service = Service(Config.EDGE_DRIVER_PATH) cls.driver = webdriver.Edge(service=service) cls.driver.maximize_window() cls.login_actions = LoginPageActions(cls.driver) cls.student_actions = StudentPageActions(cls.driver) # 登录系统 cls.login_actions.open_login_page() cls.login_actions.input_login_username(TestData.LOGIN_INFO["username"]) cls.login_actions.input_login_password(TestData.LOGIN_INFO["password"]) cls.login_actions.click_login_submit_btn() if not cls.login_actions.is_login_success(): raise Exception("登录失败,终止测试") @classmethod def tearDownClass(cls): cls.driver.quit() def setUp(self): # 用例前置:进入学生列表 self.student_actions.click_user_manage_menu() self.driver.implicitly_wait(Config.SHORT_WAIT) self.student_actions.click_student_list_menu() self.student_actions.wait_for_page_load() # 用例1:添加学生 def test_001_add_student(self): data = TestData.STUDENT_INFO self.student_actions.click_add_student_btn() self.driver.implicitly_wait(Config.SHORT_WAIT) time.sleep(1) self.student_actions.input_student_username(data["username"]) self.student_actions.input_student_password(data["password"]) self.student_actions.input_student_real_name(data["real_name"]) self.student_actions.click_grade_select_box() self.student_actions.click_grade_1_option() self.student_actions.click_student_submit_btn() self.student_actions.handle_alert_popup() self.assertEqual(self.student_actions.get_first_student_username(), data["username"], "test_001失败") # 用例2:查询学生 def test_002_query_student(self): data = TestData.STUDENT_INFO self.student_actions.input_query_keyword(data["username"]) self.student_actions.click_query_btn() self.assertEqual(self.student_actions.get_first_student_username(), data["username"], "test_002失败") # 用例3:修改学生年级 def test_003_edit_student_grade(self): data = TestData.STUDENT_INFO self.student_actions.input_query_keyword(data["username"]) self.student_actions.click_query_btn() self.student_actions.click_edit_student_btn() self.driver.implicitly_wait(Config.SHORT_WAIT) self.student_actions.click_grade_select_box() self.student_actions.click_grade_2_option() self.student_actions.click_student_submit_btn() self.student_actions.handle_alert_popup() self.assertEqual(self.student_actions.get_first_student_grade(), data["target_grade_2"], "test_003失败") # 用例4:禁用学生账号 def test_004_disable_student(self): data = TestData.STUDENT_INFO self.student_actions.click_status_switch_btn() self.student_actions.handle_alert_popup() self.assertEqual(self.student_actions.get_student_status_text(), data["status_disabled"], "test_004失败") # 用例5:启用学生账号 def test_005_enable_student(self): data = TestData.STUDENT_INFO self.student_actions.click_status_switch_btn() self.student_actions.handle_alert_popup() self.assertEqual(self.student_actions.get_student_status_text(), data["status_enabled"], "test_005失败") # 用例6:删除学生 def test_006_delete_student(self): data = TestData.STUDENT_INFO self.student_actions.input_query_keyword(data["username"]) self.student_actions.click_query_btn() self.student_actions.click_delete_student_btn() self.student_actions.handle_alert_popup() self.student_actions.input_query_keyword(data["username"]) self.student_actions.click_query_btn() self.assertTrue(self.student_actions.is_no_data_displayed(), "test_006失败") if __name__ == "__main__": # 按用例编号顺序执行 suite = unittest.TestSuite() suite.addTest(TestStudentManagement("test_001_add_student")) suite.addTest(TestStudentManagement("test_002_query_student")) suite.addTest(TestStudentManagement("test_003_edit_student_grade")) suite.addTest(TestStudentManagement("test_004_disable_student")) suite.addTest(TestStudentManagement("test_005_enable_student")) suite.addTest(TestStudentManagement("test_006_delete_student")) unittest.TextTestRunner(verbosity=2).run(suite)还是没有在左侧单独显示测试结果
最新发布
10-19
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值