diff --git a/.gitignore b/.gitignore index af2facc4182ebe6bfdfcef41e1064d9eec2eb299..5c026dca006259c09ffd13ac4b7a66450e6d32c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea/workspace.xml *.xml ghostdriver.log pyse/__pycache__/ @@ -8,3 +9,4 @@ pyse/reporting/report.txt test_case/__pycache__/ test_case/ghostdriver.log test_case/report/ +/pyse/mail/config_mail.py diff --git a/.idea/workspace.xml b/.idea/workspace.xml index c94b9b128954f331353db442f2a6bff12ad5cbc0..c0280c356ceadee44355d1d8083860f9496275d9 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,7 +1,10 @@ - + + + + @@ -24,10 +27,16 @@ - - - - + + + + + + + + + + @@ -48,11 +57,17 @@ @@ -92,6 +107,8 @@ + + @@ -110,10 +127,40 @@ + + + + + + + + + + + + + + + + + + - - @@ -121,6 +168,23 @@ + + + + + + + + + + + + + + + + + @@ -205,6 +269,12 @@ + + + + + true + @@ -355,30 +425,38 @@ - + - + - - - - - - - + + + + + - - + + - + + + + + + + @@ -392,11 +470,24 @@ + + + + + + + + + + + + + + - @@ -404,7 +495,6 @@ - @@ -412,17 +502,44 @@ + + + + + + + - + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/driver/IEDriverServer.exe b/driver/IEDriverServer.exe index 549bc5a3729f7d324748c09d6325cc14928e12c2..3f27f125f00218d3b4a8da04c10328f72233f10f 100644 Binary files a/driver/IEDriverServer.exe and b/driver/IEDriverServer.exe differ diff --git a/driver/MicrosoftWebDriver.exe b/driver/MicrosoftWebDriver.exe new file mode 100644 index 0000000000000000000000000000000000000000..e850f62bc1b4703f6f9b91f824bf83b94bac6d48 Binary files /dev/null and b/driver/MicrosoftWebDriver.exe differ diff --git "a/pyse/document/\344\272\214\346\254\241\345\260\201\350\243\205\347\232\204\346\226\271\346\263\225.mdown" "b/pyse/document/\344\272\214\346\254\241\345\260\201\350\243\205\347\232\204\346\226\271\346\263\225.mdown" index 3874b320db86dfb69b31f1c33e9acf40089b9ca2..bb1544c1fda6f4e1c98e0b3fbebdcbfa41cf5146 100644 --- "a/pyse/document/\344\272\214\346\254\241\345\260\201\350\243\205\347\232\204\346\226\271\346\263\225.mdown" +++ "b/pyse/document/\344\272\214\346\254\241\345\260\201\350\243\205\347\232\204\346\226\271\346\263\225.mdown" @@ -28,10 +28,13 @@ > 点击页面上的链接文字 13. click() > 增加了元素是否可见的判断,以及异常保护 +> 增加了无元素点击的情况 14. double_click() > 双击页面元素 15. right_click() > 右键点击后,可以控制鼠标选择弹出菜单 +16. move_by_offset() +> 按坐标值移动鼠标 16. open_new_window() > 增加了元素是否可见的判断,以及异常保护 17. selectWindow() @@ -46,11 +49,15 @@ > 针对不同浏览器有不同的处理方法 21. pressKeyboard() > 发送键盘上特定的按键,如enter, f12等 -> 参数为key_code +> 参数为*key_code,如Keys.ENTER/Keys.DOWN +> 更新代码为selenium方法,需导入Keys类 22. drag_and_drop() > 拖拽指定元素到目标位置 23. js() > 可以执行js脚本操作 +> 增加了参数的功能 +24. focus_element() +> 通过js操作使元素在界面上可见 24. get_title() > 返回页面的标题 25. get_url() diff --git "a/pyse/document/\351\224\256\347\233\230\351\224\256\344\270\216\350\231\232\346\213\237\351\224\256\347\240\201\345\257\271\347\205\247\350\241\250.txt" "b/pyse/document/\351\224\256\347\233\230\351\224\256\344\270\216\350\231\232\346\213\237\351\224\256\347\240\201\345\257\271\347\205\247\350\241\250.txt" index 9e54f6746a691b6626606159c93c8831f1fe711a..e4ffc5f09b3d561052d827b663b4818f6d87e7d6 100644 --- "a/pyse/document/\351\224\256\347\233\230\351\224\256\344\270\216\350\231\232\346\213\237\351\224\256\347\240\201\345\257\271\347\205\247\350\241\250.txt" +++ "b/pyse/document/\351\224\256\347\233\230\351\224\256\344\270\216\350\231\232\346\213\237\351\224\256\347\240\201\345\257\271\347\205\247\350\241\250.txt" @@ -1,4 +1,4 @@ -键盘键与虚拟键码对照表 +键盘键与虚拟键码对照表 字母和数字键 数字小键盘的键 功能键 其它键 @@ -38,4 +38,74 @@  6   54         7   55         8   56        - 9   57   \ No newline at end of file + 9   57   + + + NULL = '\ue000' + CANCEL = '\ue001' # ^break + HELP = '\ue002' + BACKSPACE = '\ue003' + BACK_SPACE = BACKSPACE + TAB = '\ue004' + CLEAR = '\ue005' + RETURN = '\ue006' + ENTER = '\ue007' + SHIFT = '\ue008' + LEFT_SHIFT = SHIFT + CONTROL = '\ue009' + LEFT_CONTROL = CONTROL + ALT = '\ue00a' + LEFT_ALT = ALT + PAUSE = '\ue00b' + ESCAPE = '\ue00c' + SPACE = '\ue00d' + PAGE_UP = '\ue00e' + PAGE_DOWN = '\ue00f' + END = '\ue010' + HOME = '\ue011' + LEFT = '\ue012' + ARROW_LEFT = LEFT + UP = '\ue013' + ARROW_UP = UP + RIGHT = '\ue014' + ARROW_RIGHT = RIGHT + DOWN = '\ue015' + ARROW_DOWN = DOWN + INSERT = '\ue016' + DELETE = '\ue017' + SEMICOLON = '\ue018' + EQUALS = '\ue019' + + NUMPAD0 = '\ue01a' # number pad keys + NUMPAD1 = '\ue01b' + NUMPAD2 = '\ue01c' + NUMPAD3 = '\ue01d' + NUMPAD4 = '\ue01e' + NUMPAD5 = '\ue01f' + NUMPAD6 = '\ue020' + NUMPAD7 = '\ue021' + NUMPAD8 = '\ue022' + NUMPAD9 = '\ue023' + MULTIPLY = '\ue024' + ADD = '\ue025' + SEPARATOR = '\ue026' + SUBTRACT = '\ue027' + DECIMAL = '\ue028' + DIVIDE = '\ue029' + + F1 = '\ue031' # function keys + F2 = '\ue032' + F3 = '\ue033' + F4 = '\ue034' + F5 = '\ue035' + F6 = '\ue036' + F7 = '\ue037' + F8 = '\ue038' + F9 = '\ue039' + F10 = '\ue03a' + F11 = '\ue03b' + F12 = '\ue03c' + + META = '\ue03d' + COMMAND = '\ue03d' + diff --git a/pyse/pyse.py b/pyse/pyse.py index 58a8e5d4dd7ada1bc6633b6be580b1ae80017140..5dfe888709655909b2a712f9b8d39047e85cf5ae 100644 --- a/pyse/pyse.py +++ b/pyse/pyse.py @@ -12,6 +12,7 @@ from selenium.common.exceptions import StaleElementReferenceException from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys import sys import time import win32api @@ -62,7 +63,7 @@ class Pyse(object): except Exception: print("Not found %s browser,You can enter 'ie', 'ff', 'opera', 'phantomjs', 'edge' or 'chrome'." % self.browser) - def element_wait(self, xpath, secs=30): + def element_wait(self, xpath, secs=100): ''' Waiting for an element to display. @@ -124,7 +125,7 @@ class Pyse(object): if pause_time <= 0: time.sleep(1) else: - print("Pause %s s" % pause_time) + # print("Pause %s s" % pause_time) time.sleep(pause_time) # 7 method to deal with the basic operator. @@ -224,18 +225,23 @@ class Pyse(object): self.driver.find_element_by_partial_link_text(text).click() print('Open the %s link' % text) - def click(self, xpath): + def click(self, xpath=None): """ Click the page element. :Usage: driver.click("xpath=>//*[@id='el']") """ - self.pause(self.pause_time) - self.element_wait(xpath) - el = self.get_element(xpath) - el.click() - print("Clicked element:", xpath) + if xpath: + self.pause(self.pause_time) + self.element_wait(xpath) + el = self.get_element(xpath) + el.click() + print("Clicked element:", xpath) + else: + ActionChains(self.driver).click().perform() + print("Click at the offset.") + def double_click(self, xpath): """ @@ -269,6 +275,10 @@ class Pyse(object): print('Right click the center of the element:', xpath) else: ActionChains(self.driver).context_click(el).perform() + # for i in range(down_num): + # ActionChains(self.driver).send_keys(Keys.DOWN).perform() + # time.sleep(1) + # ActionChains(self.driver).send_keys(Keys.ENTER).perform() for i in range(down_num): win32api.keybd_event(40, 0, 0, 0) win32api.keybd_event(40, 0, win32con.KEYEVENTF_KEYUP, 0) @@ -363,28 +373,59 @@ class Pyse(object): if 'chrome' == self.browser: ActionChains(self.driver).move_to_element(el).perform() - print('Mouseover at %s' % xpath) + print('[chrome]Mouseover at %s' % xpath) # Firefox and IE require multiple cycles, more than twice, to cause a hovering effect. elif self.browser in ('ff', 'firefox', 'ie', 'internet explorer'): for cycle in range(5): ActionChains(self.driver).move_to_element(el).perform() - print('Mouseover at %s' % xpath) + print('[ff]Mouseover at %s' % xpath) else: print('Other browsers can be tested.') - def press_keyboard(self, key_code): + def move_by_offset(self, xoffset, yoffset): + """ + Moving the mouse to an offset from current mouse position. + + :Args: + - xoffset: X offset to move to, as a positive or negative integer. + - yoffset: Y offset to move to, as a positive or negative integer. + + :Usage: + driver.move_by_offset(100, 100) + """ + self.pause(self.pause_time) + ActionChains(self.driver).move_by_offset(xoffset, yoffset).perform() + print('Move cursor to: %d, %d' % (xoffset, yoffset)) + + def focus_element(self, xpath): + """ + Make the element displayed on the page. + + :Args: + - xpath: the element's xpath + + :Usage: + driver.focus_element("link_text=>图片") + """ + self.pause(self.pause_time) + self.js("arguments[0].scrollIntoView();", self.get_element(xpath)) + + def press_keyboard(self, *key_code): """ Mimic system-level keyboard event :Args: - - key_code - such as KeyEvent.TAB, KeyEvent.F11 + - key_code - such as Keys.TAB, Keys.F11 Usage: - driver.press_keyboard(40) + driver.press_keyboard(Keys.TAB) + driver.press_keyboard(Keys.CONTROL, 'a') """ self.pause(self.pause_time) - win32api.keybd_event(key_code, 0, 0, 0) - win32api.keybd_event(key_code, 0, win32con.KEYEVENTF_KEYUP, 0) + ActionChains(self.driver).send_keys(key_code).perform() + print('Sends keys successfully.') + # win32api.keybd_event(key_code, 0, 0, 0) + # win32api.keybd_event(key_code, 0, win32con.KEYEVENTF_KEYUP, 0) def drag_and_drop(self, el_xpath, ta_xpath): """ @@ -402,14 +443,15 @@ class Pyse(object): ActionChains(driver).drag_and_drop(element, target).perform() print('Moved element %s to %s' % (el_xpath, ta_xpath)) - def js(self, script): + def js(self, script, *args): """ Execute JavaScript scripts. Usage: driver.js("window.scrollTo(200,1000);") """ - self.driver.execute_script(script) + self.driver.execute_script(script, *args) + print('Execute script: %s' %(script)) # 6 methods to deal with the get contents operator. def get_title(self): @@ -513,6 +555,7 @@ class Pyse(object): driver.accept_alert() """ self.driver.switch_to.alert.accept() + print('Confirm the popup window.') def dismiss_alert(self): """ @@ -522,6 +565,7 @@ class Pyse(object): driver.dismiss_alert() """ self.driver.switch_to.alert.dismiss() + print('Dismiss the popup window.') if __name__ == '__main__': diff --git a/report/2017-09-18_17_49_47result.html b/report/2017-09-18_17_49_47result.html deleted file mode 100644 index ada90f375413c40d4d4220eaaefb52440be9dc13..0000000000000000000000000000000000000000 --- a/report/2017-09-18_17_49_47result.html +++ /dev/null @@ -1,396 +0,0 @@ - - - - - 所有测试用例的测试报告 - - - - - - - - - -
-

所有测试用例的测试报告

-

Start Time: 2017-09-18 17:49:47

-

Duration: 0:01:14.929786

-

Status: Pass 2 Failure 1

- -

测试环境:win10, 浏览器:Phantomjs

-
- - - -

Show -Summary -Failed -All -

- -------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Test Group/Test caseCountPassFailErrorViewScreenshot
Test IDipsa_case.IPSATest: ipsa test 1100Detailimage
case 001
test_baidu: 预设结果为Pass
- - - - pass - - - - - ScreenShot - - - -
Test IDunittest_case.BaiduTest: baidu test 2110Detailimage
case 002
test_case1: 预设结果Pass
- - - - pass - - - - - ScreenShot - - - -
case 003
test_case2: 预设结果Fail
- - - - fail - - - - - ScreenShot - - - -
Total3210  
- -
 
- - - diff --git a/report/2017-09-21_15_33_31result.html b/report/2017-09-21_15_33_31result.html deleted file mode 100644 index ab10034f238783f26721a880f5537d6fcf10d55c..0000000000000000000000000000000000000000 --- a/report/2017-09-21_15_33_31result.html +++ /dev/null @@ -1,371 +0,0 @@ - - - - - 所有测试用例的测试报告 - - - - - - - - - -
- - -

测试环境:win10, 浏览器:Phantomjs

- - - -
- - - -
-

- -------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
测试套件/测试用例总数通过失败错误查看
ipsa_case.IPSATest: ipsa test 1100详情
test_baidu: 预设结果为Pass
- - - - 通过 - - - - -
unittest_case.BaiduTest: baidu test 2110详情
test_case1: 预设结果Pass
- - - - 通过 - - - - -
test_case2: 预设结果Fail
- - - - 失败 - - - - -
总计3210 
- -
 
- -
- - diff --git a/report/2017-09-21_16_23_55result.html b/report/2017-09-21_16_23_55result.html deleted file mode 100644 index 3b52e0d74409a13388b286ffe463f3fd820d6a1c..0000000000000000000000000000000000000000 --- a/report/2017-09-21_16_23_55result.html +++ /dev/null @@ -1,394 +0,0 @@ - - - - - 所有测试用例的测试报告 - - - - - - - - - -
-

所有测试用例的测试报告

-

开始时间: 2017-09-21 16:23:55

-

运行耗时: 0:01:16.307702

-

测试结果: 通过:2 失败:1

- -

测试环境:win10, 浏览器:Phantomjs

-
- - - -

查看方式: -总体结果 -只显示失败用例 -全部显示 -

- -------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
测试套件/测试用例总数通过失败错误查看截图
测试序号ipsa_case.IPSATest: ipsa test 1100详情
case 001
test_baidu: 预设结果为Pass
- - - - 通过 - - - - - 点击查看图片 - - - -
测试序号unittest_case.BaiduTest: baidu test 2110详情
case 002
test_case1: 预设结果Pass
- - - - 通过 - - - - - 点击查看图片 - - - -
case 003
test_case2: 预设结果Fail
- - - - 失败 - - - - - 点击查看图片 - - - -
总计3210  
- -
 
- - - diff --git a/report/2017-09-22_17_57_42result.html b/report/2017-09-22_17_57_42result.html deleted file mode 100644 index 58ff98e86265ebd19076e98a907738b488d0cf44..0000000000000000000000000000000000000000 --- a/report/2017-09-22_17_57_42result.html +++ /dev/null @@ -1,401 +0,0 @@ - - - - - 所有测试用例的测试报告 - - - - - - - - - -
-

所有测试用例的测试报告

-

开始时间: 2017-09-22 17:57:42

-

运行耗时: 0:01:42.054751

-

测试结果: 通过:1 失败:1 错误:1

- -

测试环境:win10, 浏览器:Phantomjs

-
- - - -

查看方式: -总体结果 -只显示失败用例 -全部显示 -

- -------- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
测试套件/测试用例总数通过失败错误查看截图
测试序号ipsa_case.IPSATest: ipsa test 1100详情
case 001
test_baidu: 预设结果为Pass
- - - - 通过 - - - - - 点击查看图片 - - - -
测试序号unittest_case.BaiduTest: baidu test 2011详情
case 002
test_case1: 预设结果Pass
- - - - 错误 - - - - - 点击查看图片 - - - -
case 003
test_case2: 预设结果Fail
- - - - 失败 - - - - - 点击查看图片 - - - -
总计3111  
- -
 
- - - diff --git a/report/image/001.png b/report/image/001.png index 8bcb6f12c828e58d7cf3a7d7fdd5ad186247b3f9..ea4c22d6bc17cfef300ae54fc0f806431859d193 100644 Binary files a/report/image/001.png and b/report/image/001.png differ diff --git a/report/image/002.png b/report/image/002.png index 062cab61d2e08bbc88ab0fb4106209ef548112ff..d17a332d04586468086b78b55c06293c7ad298a1 100644 Binary files a/report/image/002.png and b/report/image/002.png differ diff --git a/report/image/003.png b/report/image/003.png index bfb6f94554e0817445a3514711ef45f230f4282c..03f7e568b658b399069557d46e8e41376c9c8027 100644 Binary files a/report/image/003.png and b/report/image/003.png differ diff --git a/run_test.py b/run_test.py index b27daa6318a820a88b6ee39d40b7cc5f4afc1226..4d67f2f5156af345bbf6b208a0b44cf291a30960 100644 --- a/run_test.py +++ b/run_test.py @@ -1,11 +1,16 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- + from pyse import TestRunner +''' +说明: +'./test_case' : 指定测试目录,会在指定的目录同级生成report目录。 +'测试报告DEMO演示' : 测试项目标题。 +'测试环境:python3.5, 操作系统:Windows 10' : 测试环境描述。 +''' + if __name__ == '__main__': - # 选择测试用例所在的目录(./test_case) - test_pro = TestRunner('./test_case') - # 定义测试报告的名称和描述 - test_pro.run(title_text='百度和IPSA的测试报告', description_text='环境:Windows10 浏览器: PhantJS和Chrome') - # 报告生成后发送邮件 - test_pro.send_mail() + test_pro = TestRunner("./test_case") + test_pro.run(title_text='测试报告DEMO演示', description_text='测试环境:python3.5, 操作系统:Windows 10') + # test_pro.send_mail() diff --git a/test_case/unittest_case.py b/test_case/baidu_case.py similarity index 71% rename from test_case/unittest_case.py rename to test_case/baidu_case.py index 8fd2359773eb8b921926be084d93b69c89d6b83b..78edda93ea4ce428bb209c51d92e80bfeb6398a1 100644 --- a/test_case/unittest_case.py +++ b/test_case/baidu_case.py @@ -5,7 +5,6 @@ Created on 2016年2月15日 """ from pyse import Pyse, TestRunner, myunit from time import sleep -import unittest ''' ============运行测试用例说明======== @@ -17,28 +16,27 @@ run(title_text = u'xx项目测试报告', description_text = u'环境:window 7 ''' - class BaiduTest(myunit.MyTest): """ baidu test """ - def test_case1(self): - """ 预设结果Pass """ - self.driver = Pyse("chrome") + def test_search1(self): + """ 百度搜索:预设结果Error """ + self.driver = Pyse("ff") driver = self.driver driver.open("https://www.baidu.com") - driver.type("xpath=>//*[@id='kww']", u"sina yytan02") + driver.type("xpath=>//*[@id='kww']", "自动化测试") driver.click("css=>#su") sleep(5) title = driver.get_title() self.assertEqual(title, "sina yytan02_百度搜索") - @unittest.skip('no reason') - def test_case2(self): - """ 预设结果Fail """ - self.driver = Pyse("chrome") + # @unittest.skip('no reason') + def test_search2(self): + """ 百度搜索:预设结果FAIL """ + self.driver = Pyse("edge") driver = self.driver driver.open("https://www.baidu.com") - driver.type("xpath=>//*[@id='kw']", u"谭元元的博客") + driver.type("xpath=>//*[@id='kw']", "谭元元的博客") driver.click("xpath=>//*[@id='su']") sleep(5) title = driver.get_title() @@ -48,6 +46,6 @@ class BaiduTest(myunit.MyTest): if __name__ == '__main__': print('start') test_pro = TestRunner() - test_pro.run('单元测试的测试报告', '测试环境:win10, 浏览器:chrome') + test_pro.run('测试报告DEMO演示','测试环境:python3.5, 操作系统:Windows 10') # test_pro.send_mail() print('end') diff --git a/test_case/ipsa_case.py b/test_case/ipsa_case.py index c1fb4d3d79c08c4b995aa515e750520ee8d4e6cf..f80f37852dcb16180121922210a837005887e24b 100644 --- a/test_case/ipsa_case.py +++ b/test_case/ipsa_case.py @@ -21,10 +21,10 @@ run(title_text = u'xx项目测试报告', description_text = u'ENV:window 7 C class IPSATest(myunit.MyTest): """ ipsa test """ - @unittest.skip('ff') - def test_case(self): - """ 验证登录用户名 """ - self.driver = Pyse("ff") + # @unittest.skip('ff') + def test_login(self): + """ 验证登录功能: 预设结果PASS """ + self.driver = Pyse("chrome") driver = self.driver driver.open("https://passport.isoftstone.com/") # 输入用户名 @@ -33,14 +33,16 @@ class IPSATest(myunit.MyTest): driver.type("xpath=>//*[@id='emp_Password']", "game2015!") # 点击提交按钮 driver.click("xpath=>//*[@id='BtnLogin']") - # 打印待判断处的文本信息 - print(driver.get_text("xpath=>//*[@id='Greeting']/p[1]")) + # 实际待判断处的文本信息 + actual_content = driver.get_text("xpath=>//*[@id='Greeting']/p[1]") # 和预期结果进行比较 - self.assertEqual(u"Hi, 谭元元", driver.get_text("//*[@id='Greeting']/p[1]")) + expect_rlt = "Hi, 谭元元" + self.assertEqual(expect_rlt, actual_content) + @unittest.skip('ff') def test_baidu(self): """ 预设结果为Pass """ - self.driver = Pyse('phantomjs') + self.driver = Pyse('chrome') driver = self.driver driver.open("https://www.baidu.com") driver.type("xpath=>//*[@id='kw']", "pyse自动化测试") @@ -53,4 +55,4 @@ if __name__ == '__main__': # unittest.main() test_pro = TestRunner() # test_pro.run() - test_pro.run('我自己的测试报告', '测试环境:python3.5, windows10') + test_pro.run('测试报告DEMO演示','测试环境:python3.5, 操作系统:Windows 10')