From b1d1c8155975f5b3f3ac9e97a251e894b68cb89a Mon Sep 17 00:00:00 2001 From: easonhan Date: Tue, 23 Aug 2016 11:37:52 +0800 Subject: [PATCH 01/11] refactor for gitbook --- .gitignore | 2 + 00/init.java.md | 3 + 00/init.md | 3 + 00/init.py.md | 10 ++- 01/start_browser.py | 3 +- 17/pagination.md | 9 ++- README.md | 104 ++++++++++++--------------- README.old.md | 126 +++++++++++++++++++++++++++++++++ SUMMARY.md | 168 ++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 358 insertions(+), 70 deletions(-) create mode 100644 00/init.java.md create mode 100644 00/init.md create mode 100644 README.old.md create mode 100644 SUMMARY.md diff --git a/.gitignore b/.gitignore index f8893d9..82a7485 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,5 @@ # Ignore vim swp files. *.swp +/_book + diff --git a/00/init.java.md b/00/init.java.md new file mode 100644 index 0000000..ac76616 --- /dev/null +++ b/00/init.java.md @@ -0,0 +1,3 @@ +# 安装java及webdriver的开发环境 + +TODO diff --git a/00/init.md b/00/init.md new file mode 100644 index 0000000..9ec059a --- /dev/null +++ b/00/init.md @@ -0,0 +1,3 @@ +# 安装ruby及webdriver的开发环境 + +TODO diff --git a/00/init.py.md b/00/init.py.md index 7932197..325b3cb 100644 --- a/00/init.py.md +++ b/00/init.py.md @@ -16,22 +16,22 @@ 只需要2步就可以安装完毕。 -### 安装[active-python](http://www.activestate.com/activepython/) +**安装[active-python](http://www.activestate.com/activepython/)** 从[这里](http://www.activestate.com/activepython/downloads)下载active python2.7.5的windows安装版本,注意,如果是64位系统,则需要选择(64-bit, x64)版本下载。 双击打开下载的文件,直接下一步安装既可,很简单,什么都不需要更改。 -#### 注意,如果你的机器安装了360转坑小白伪杀毒工具的话,请关闭360再进行安装。 +*注意,如果你的机器安装了360等专坑小白伪杀毒工具的话,请关闭360再进行安装。* -### 安装selenium webdriver +**安装selenium webdriver** 打开命令行cmd,输入下面的命令 pip install selenium 回车后,你会看到下面的提示 - + Downloading/unpacking selenium Downloading selenium-2.38.1.tar.gz (2.5MB): 2.5MB downloaded Running setup.py egg_info for package selenium @@ -43,5 +43,3 @@ Cleaning up... 现在大功告成,python的webdriver之旅即将展开。 - - diff --git a/01/start_browser.py b/01/start_browser.py index a43d8be..fad0d87 100644 --- a/01/start_browser.py +++ b/01/start_browser.py @@ -1,3 +1,4 @@ from selenium import webdriver -dr = webdriver.Chrome() +#dr = webdriver.Chrome() +dr = webdriver.Firefox() diff --git a/17/pagination.md b/17/pagination.md index aeb989f..99e685c 100644 --- a/17/pagination.md +++ b/17/pagination.md @@ -14,7 +14,7 @@ 下面的代码演示了如何获取分页的总数以及当前是第几页 ### pagination.html -``` +```html @@ -30,7 +30,7 @@ }); - +

Pagination

@@ -51,11 +51,11 @@ - + ``` ### pagination.rb -``` +```ruby #encoding: utf-8 require 'selenium-webdriver' @@ -73,4 +73,3 @@ puts "current page is #{current_page.text}" dr.quit() ``` - diff --git a/README.md b/README.md index 5b087c3..7cfa31c 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,48 @@ -webdriver实用指南ruby版本 -========================= +# 简介 -不用担心,html版本的《webdriver实用指南ruby版本》是 __永久免费__ 的。 +几年前我在github上写了webdriver实用指南,由于github本身设计的目的是为了承载代码,而不是承载书籍,用户观感不佳,所以现在将其重构至gitbook。 +## 内容预览 -目录如下 -======== +### python篇 + +* [安装开发环境](/00/init.py.md) +* [启动浏览器](/01/start_browser.py.md) +* [关闭浏览器](/02/close_browser.py.md) +* [浏览器最大化](/03/maximize_browser.py.md) +* [设置浏览器大小](/04/resize_browser.py.md) +* [访问链接](/05/get.py.md) +* [打印当前页面的title及url](06/title_and_url.py.md) +* [前进和后退](07/forword_and_back.py.md) +* [简单的对象定位](/08/simple_locate.py.md) +* [定位一组对象](/09/find_elements.py.md) +* [层级定位](/10/level_locate.py.md) +* [操作测试对象](/11/operate_element.py.md) +* [send keys模拟按键输入](/12/send_keys.py.md) +* [处理button group](/13/button_group.py.md) +* [处理button dropdown](/14/button_dropdown.py.md) +* [处理navs](/15/navs.py.md) +* [处理分页](/17/pagination.py.md) +* [处理面包屑](/16/breadcrumb.py.md) +* [处理对话框新式的模态窗口](/18/modal.py.md) +* [获取测试对象的属性及内容](/19/attribute.py.md) +* [获取测试对象的css属性](/20/css.py.md) +* [获取测试对象的状态](/21/status.py.md) +* [处理表单元素](/22/form.py.md) +* [执行js](/23/js.py.md) +* [处理alert/confirm/prompt](/24/alert.py.md) +* [wait](/25/wait.py.md) +* [定位frame中的元素](/26/frame.py.md) +* [action](/27/action.py.md) +* [上传文件](/28/upload_file.py.md) +* [下载](/29/download.py.md) +* [超时设置](/30/timeout.py.md) +* [Remote Webdriver](/31/remote.md) +* [cookie与自动登陆](/32/cookie.py.md) + +----------------------------------------------------------- + +### ruby篇 * [启动浏览器](/01/start_browser.md) * [关闭浏览器](/02/close_browser.md) @@ -23,6 +60,7 @@ webdriver实用指南ruby版本 * [处理button dropdown](/14/button_dropdown.md) * [处理navs](/15/navs.md) * [处理面包屑](/16/breadcrumb.md) +* [处理分页](/17/pagination.md) * [处理对话框新式的模态窗口](/18/modal.md) * [获取测试对象的属性及内容](/19/attribute.md) * [获取测试对象的css属性](/20/css.md) @@ -39,16 +77,8 @@ webdriver实用指南ruby版本 * [Remote Webdriver](/31/remote.md) * [cookie与自动登陆](/32/cookie.md) ------------------------------------------------------------ - -webdriver实用指南java版本 -========================= - -不用担心,html版本的《webdriver实用指南java版本》是 __永久免费__ 的。 - - -目录如下 -======== +-------------------------------------- +### java篇 * [启动浏览器](/01/start_browser.java.md) * [关闭浏览器](/02/close_browser.java.md) @@ -66,6 +96,7 @@ webdriver实用指南java版本 * [处理button dropdown](/14/button_dropdown.java.md) * [处理navs](/15/navs.java.md) * [处理面包屑](/16/breadcrumb.java.md) +* [处理分页](/17/pagination.java.md) * [处理对话框新式的模态窗口](/18/modal.java.md) * [获取测试对象的属性及内容](/19/attribute.java.md) * [获取测试对象的css属性](/20/css.java.md) @@ -81,46 +112,3 @@ webdriver实用指南java版本 * [超时设置](/30/timeout.java.md) * [Remote Webdriver](/31/remote.md) * [cookie与自动登陆](/32/cookie.java.md) - ------------------------------------------------------------ - -webdriver实用指南python版本 -========================= - -不用担心,html版本的《webdriver实用指南python版本》是 __永久免费__ 的。 - -目录如下 -======== - -* [安装开发环境](/00/init.py.md) -* [启动浏览器](/01/start_browser.py.md) -* [关闭浏览器](/02/close_browser.py.md) -* [浏览器最大化](/03/maximize_browser.py.md) -* [设置浏览器大小](/04/resize_browser.py.md) -* [访问链接](/05/get.py.md) -* [打印当前页面的title及url](06/title_and_url.py.md) -* [前进和后退](07/forword_and_back.py.md) -* [简单的对象定位](/08/simple_locate.py.md) -* [定位一组对象](/09/find_elements.py.md) -* [层级定位](/10/level_locate.py.md) -* [操作测试对象](/11/operate_element.py.md) -* [send keys模拟按键输入](/12/send_keys.py.md) -* [处理button group](/13/button_group.py.md) -* [处理button dropdown](/14/button_dropdown.py.md) -* [处理navs](/15/navs.py.md) -* [处理面包屑](/16/breadcrumb.py.md) -* [处理对话框新式的模态窗口](/18/modal.py.md) -* [获取测试对象的属性及内容](/19/attribute.py.md) -* [获取测试对象的css属性](/20/css.py.md) -* [获取测试对象的状态](/21/status.py.md) -* [处理表单元素](/22/form.py.md) -* [执行js](/23/js.py.md) -* [处理alert/confirm/prompt](/24/alert.py.md) -* [wait](/25/wait.py.md) -* [定位frame中的元素](/26/frame.py.md) -* [action](/27/action.py.md) -* [上传文件](/28/upload_file.py.md) -* [下载](/29/download.py.md) -* [超时设置](/30/timeout.py.md) -* [Remote Webdriver](/31/remote.md) -* [cookie与自动登陆](/32/cookie.py.md) diff --git a/README.old.md b/README.old.md new file mode 100644 index 0000000..5b087c3 --- /dev/null +++ b/README.old.md @@ -0,0 +1,126 @@ +webdriver实用指南ruby版本 +========================= + +不用担心,html版本的《webdriver实用指南ruby版本》是 __永久免费__ 的。 + + +目录如下 +======== + +* [启动浏览器](/01/start_browser.md) +* [关闭浏览器](/02/close_browser.md) +* [浏览器最大化](/03/maximize_browser.md) +* [设置浏览器大小](/04/resize_browser.md) +* [访问链接](/05/get.md) +* [打印当前页面的title及url](06/title_and_url.md) +* [前进和后退](07/forword_and_back.md) +* [简单的对象定位](/08/simple_locate.md) +* [定位一组对象](/09/find_elements.md) +* [层级定位](/10/level_locate.md) +* [操作测试对象](/11/operate_element.md) +* [send keys模拟按键输入](/12/send_keys.md) +* [处理button group](/13/button_group.md) +* [处理button dropdown](/14/button_dropdown.md) +* [处理navs](/15/navs.md) +* [处理面包屑](/16/breadcrumb.md) +* [处理对话框新式的模态窗口](/18/modal.md) +* [获取测试对象的属性及内容](/19/attribute.md) +* [获取测试对象的css属性](/20/css.md) +* [获取测试对象的状态](/21/status.md) +* [处理表单元素](/22/form.md) +* [执行js](/23/js.md) +* [处理alert/confirm/prompt](/24/alert.md) +* [wait](/25/wait.md) +* [定位frame中的元素](/26/frame.md) +* [action](/27/action.md) +* [上传文件](/28/upload_file.md) +* [下载](/29/download.md) +* [超时设置](/30/timeout.md) +* [Remote Webdriver](/31/remote.md) +* [cookie与自动登陆](/32/cookie.md) + +----------------------------------------------------------- + +webdriver实用指南java版本 +========================= + +不用担心,html版本的《webdriver实用指南java版本》是 __永久免费__ 的。 + + +目录如下 +======== + +* [启动浏览器](/01/start_browser.java.md) +* [关闭浏览器](/02/close_browser.java.md) +* [浏览器最大化](/03/maximize_browser.java.md) +* [设置浏览器大小](/04/resize_browser.java.md) +* [访问链接](/05/get.java.md) +* [打印当前页面的title及url](06/title_and_url.java.md) +* [前进和后退](07/forword_and_back.java.md) +* [简单的对象定位](/08/simple_locate.java.md) +* [定位一组对象](/09/find_elements.java.md) +* [层级定位](/10/level_locate.java.md) +* [操作测试对象](/11/operate_element.java.md) +* [send keys模拟按键输入](/12/send_keys.java.md) +* [处理button group](/13/button_group.java.md) +* [处理button dropdown](/14/button_dropdown.java.md) +* [处理navs](/15/navs.java.md) +* [处理面包屑](/16/breadcrumb.java.md) +* [处理对话框新式的模态窗口](/18/modal.java.md) +* [获取测试对象的属性及内容](/19/attribute.java.md) +* [获取测试对象的css属性](/20/css.java.md) +* [获取测试对象的状态](/21/status.java.md) +* [处理表单元素](/22/form.java.md) +* [执行js](/23/js.java.md) +* [处理alert/confirm/prompt](/24/alert.java.md) +* [wait](/25/wait.java.md) +* [定位frame中的元素](/26/frame.java.md) +* [action](/27/action.java.md) +* [上传文件](/28/upload_file.java.md) +* [下载](/29/download.java.md) +* [超时设置](/30/timeout.java.md) +* [Remote Webdriver](/31/remote.md) +* [cookie与自动登陆](/32/cookie.java.md) + +----------------------------------------------------------- + +webdriver实用指南python版本 +========================= + +不用担心,html版本的《webdriver实用指南python版本》是 __永久免费__ 的。 + +目录如下 +======== + +* [安装开发环境](/00/init.py.md) +* [启动浏览器](/01/start_browser.py.md) +* [关闭浏览器](/02/close_browser.py.md) +* [浏览器最大化](/03/maximize_browser.py.md) +* [设置浏览器大小](/04/resize_browser.py.md) +* [访问链接](/05/get.py.md) +* [打印当前页面的title及url](06/title_and_url.py.md) +* [前进和后退](07/forword_and_back.py.md) +* [简单的对象定位](/08/simple_locate.py.md) +* [定位一组对象](/09/find_elements.py.md) +* [层级定位](/10/level_locate.py.md) +* [操作测试对象](/11/operate_element.py.md) +* [send keys模拟按键输入](/12/send_keys.py.md) +* [处理button group](/13/button_group.py.md) +* [处理button dropdown](/14/button_dropdown.py.md) +* [处理navs](/15/navs.py.md) +* [处理面包屑](/16/breadcrumb.py.md) +* [处理对话框新式的模态窗口](/18/modal.py.md) +* [获取测试对象的属性及内容](/19/attribute.py.md) +* [获取测试对象的css属性](/20/css.py.md) +* [获取测试对象的状态](/21/status.py.md) +* [处理表单元素](/22/form.py.md) +* [执行js](/23/js.py.md) +* [处理alert/confirm/prompt](/24/alert.py.md) +* [wait](/25/wait.py.md) +* [定位frame中的元素](/26/frame.py.md) +* [action](/27/action.py.md) +* [上传文件](/28/upload_file.py.md) +* [下载](/29/download.py.md) +* [超时设置](/30/timeout.py.md) +* [Remote Webdriver](/31/remote.md) +* [cookie与自动登陆](/32/cookie.py.md) diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 0000000..49899d9 --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,168 @@ +# Summary + +* [简介](README.md) + +* 00: 初始化环境 + * [python篇](00/init.py.md) + * [Ruby篇](00/init.md) + * [Java篇](00/init.java.md) + +* 01: 打开浏览器 + * [python篇](01/start_browser.py.md) + * [Ruby篇](01/start_browser.md) + * [Java篇](01/start_browser.java.md) + +* 02: 关闭浏览器 + * [python篇](02/close_browser.py.md) + * [Ruby篇](02/close_browser.md) + * [Java篇](02/close_browser.java.md) + +* 03: 最大化浏览器 + * [python篇](03/maximize_browser.py.md) + * [Ruby篇](03/maximize_browser.md) + * [Java篇](03/maximize_browser.java.md) + +* 04: 设置浏览器大小 + * [python篇](04/resize_browser.py.md) + * [Ruby篇](03/resize_browser.md) + * [Java篇](03/resize_browser.java.md) + +* 05: 访问链接 + * [python篇](05/get.py.md) + * [Ruby篇](03/get.md) + * [Java篇](03/get.java.md) + +* 06: 打印当前页面的title及url + * [python篇](06/title_and_url.py.md) + * [Ruby篇](06/title_and_url.md) + * [Java篇](06/title_and_url.java.md) + +* 07: 前进和后退 + * [python篇](07/forword_and_back.py.md) + * [Ruby篇](07/forword_and_back.md) + * [Java篇](07/forword_and_back.java.md) + +* 08: 简单的对象定位 + * [python篇](08/simple_locate.py.md) + * [Ruby篇](08/simple_locate.md) + * [Java篇](08/simple_locate.java.md) + +* 09: 定位一组对象 + * [python篇](09/find_elements.py.md) + * [Ruby篇](09/find_elements.md) + * [Java篇](09/find_elements.java.md) + +* 10: 层级定位 + * [python篇](10/level_locate.py.md) + * [Ruby篇](09/level_locate.md) + * [Java篇](09/level_locate.java.md) + +* 11: 操作测试对象 + * [python篇](11/operate_element.py.md) + * [Ruby篇](11/operate_element.md) + * [Java篇](11/operate_element.java.md) + +* 12: send keys模拟按键输入 + * [python篇](12/send_keys.py.md) + * [Ruby篇](12/send_keys.md) + * [Java篇](12/send_keys.java.md) + +* 13: 处理button group + * [python篇](13/button_group.py.md) + * [Ruby篇](13/button_group.md) + * [Java篇](13/button_group.java.md) + +* 14: 处理button dropdown + * [python篇](14/button_dropdown.py.md) + * [Ruby篇](14/button_group.md) + * [Java篇](14/button_dropdown.java.md) + +* 15: 处理navs + * [python篇](15/navs.py.md) + * [Ruby篇](15/navs.md) + * [Java篇](15/navs.java.md) + +* 16: 处理面包屑 + * [python篇](16/breadcrumb.py.md) + * [Ruby篇](16/breadcrumb.md) + * [Java篇](16/breadcrumb.java.md) + +* 17: 处理分页 + * [python篇](17/pagination.py.md) + * [Ruby篇](17/pagination.md) + * [Java篇](17/pagination.java.md) + +* 18: 处理对话框(弹出层) + * [python篇](18/modal.py.md) + * [Ruby篇](18/modal.md) + * [Java篇](18/modal.java.md) + +* 19: 获取测试对象的属性及内容 + * [python篇](19/attribute.py.md) + * [Ruby篇](19/attribute.md) + * [Java篇](19/attribute.java.md) + +* 20: 获取测试对象的css属性 + * [python篇](20/css.py.md) + * [Ruby篇](20/css.md) + * [Java篇](20/css.java.md) + +* 21: 获取测试对象的状态 + * [python篇](21/status.py.md) + * [Ruby篇](21/status.md) + * [Java篇](21/status.java.md) + +* 22: 处理表单元素 + * [python篇](22/form.py.md) + * [Ruby篇](22/form.md) + * [Java篇](22/form.java.md) + +* 23: 使用selenium执行执行javascript + * [python篇](23/js.py.md) + * [Ruby篇](23/js.md) + * [Java篇](23/js.java.md) + +* 24: 处理alert/confirm/prompt(原生js弹出框) + * [python篇](24/alert.py.md) + * [Ruby篇](24/alert.md) + * [Java篇](24/alert.java.md) + +* 25: Wait + * [python篇](25/wait.py.md) + * [Ruby篇](25/wait.md) + * [Java篇](25/wait.java.md) + +* 26: 定位frame中的元素 + * [python篇](26/frame.py.md) + * [Ruby篇](26/frame.md) + * [Java篇](26/frame.java.md) + +* 27: action(模拟复杂的用户操作) + * [python篇](27/action.py.md) + * [Ruby篇](27/action.md) + * [Java篇](27/action.java.md) + +* 28: 上传文件 + * [python篇](28/upload_file.py.md) + * [Ruby篇](28/upload_file.md) + * [Java篇](28/upload_file.java.md) + +* 29: 下载文件 + * [python篇](29/download.py.md) + * [Ruby篇](29/download.md) + * [Java篇](29/download.java.md) + +* 30: 超时设置 + * [python篇](30/timeout.py.md) + * [Ruby篇](30/timeout.md) + * [Java篇](30/timeout.java.md) + +* 31: Remote Webdriver(分布式) + * [python篇](31/remote.py.md) + * [Ruby篇](31/remote.md) + * [Java篇](31/remote.java.md) + +* 32: cookie与自动登陆 + * [python篇](32/cookie.py.md) + * [Ruby篇](32/cookie.md) + * [Java篇](32/cookie.java.md) From 139f794c5940d3c3a1dedba9a0cf856d9d23af24 Mon Sep 17 00:00:00 2001 From: easonhan Date: Tue, 23 Aug 2016 12:07:40 +0800 Subject: [PATCH 02/11] add about me --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 7cfa31c..fdde220 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ 几年前我在github上写了webdriver实用指南,由于github本身设计的目的是为了承载代码,而不是承载书籍,用户观感不佳,所以现在将其重构至gitbook。 +我的blog是[乙醇的blog](http://www.cnblogs.com/nbkhic) + +如果你自学困难,想要找人辅导,与一群小伙伴一同学习的话,你可以看一下[我们的课程](http://itest.info/courses) + ## 内容预览 ### python篇 From b7089e24fb89a72b2f53c3eafb2d2d80a9c3ab06 Mon Sep 17 00:00:00 2001 From: easonhan Date: Tue, 23 Aug 2016 12:36:56 +0800 Subject: [PATCH 03/11] add gitbook address --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index fdde220..0e82c8a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ 几年前我在github上写了webdriver实用指南,由于github本身设计的目的是为了承载代码,而不是承载书籍,用户观感不佳,所以现在将其重构至gitbook。 +[gitbook地址](https://easonhan007.gitbooks.io/selenium-webdriver/content/),看着会舒服点。 + 我的blog是[乙醇的blog](http://www.cnblogs.com/nbkhic) 如果你自学困难,想要找人辅导,与一群小伙伴一同学习的话,你可以看一下[我们的课程](http://itest.info/courses) From 70544f65f0fad6c36b894ec7ce59869271c5a17a Mon Sep 17 00:00:00 2001 From: easonhan Date: Thu, 29 Sep 2016 13:38:51 +0800 Subject: [PATCH 04/11] add ec and switch windows --- 33/switch_window.py.md | 83 +++++++++++++++++++++++ README.md | 1 + expected_conditions.py | 58 ++++++++++++++++ expected_conditions.py.md | 139 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 281 insertions(+) create mode 100644 33/switch_window.py.md create mode 100644 expected_conditions.py create mode 100644 expected_conditions.py.md diff --git a/33/switch_window.py.md b/33/switch_window.py.md new file mode 100644 index 0000000..c47b8d4 --- /dev/null +++ b/33/switch_window.py.md @@ -0,0 +1,83 @@ +## 切换窗口 + +### 场景 + +切换窗口的场景其实很普遍,当你点击了一个链接之后有可能弹出一个新窗口,这时候如果你需要定位新窗口中的元素并进行操作,你就需要进行窗口切换的操作。 + +### 代码 + +switch_window.html + +```html + + + Switch Window + + + +

This is main window

+ Click to open sub window + + +``` + +sub_window.html + +```html + + + Sub Window + + + +

This is sub window

+ + +``` + +switch_window.py + +```python + +# coding: utf-8 + +from selenium import webdriver +from time import sleep +import os + +# I write this code on my MBP and I can not launch chrome using chrome driver +# use firefox instead +dr = webdriver.Firefox() +file_path = 'file:///' + os.path.abspath('switch_window.html') + +dr.get(file_path) +print dr.title +print dr.find_element_by_tag_name('h3').text + +open_new_win_link = dr.find_element_by_id('open-new-window') +open_new_win_link.click() + +# find all window handles +all_handles = dr.window_handles + +# find handle of the other window +the_other_handle = '' +for h in all_handles: + if h != dr.current_window_handle: the_other_handle = h + +#switch window +if the_other_handle: + dr.switch_to_window(the_other_handle) + print dr.title + print dr.find_element_by_tag_name('h3').text + assert dr.title == 'Sub Window' + +dr.quit + +``` + +### 思考 + +切换到新打开窗口的思路实际上就是遍历所有的窗口句柄,如果不是当前窗口的话就切换到这个句柄所代表的窗口。 + +那么问题就来了,上面的代码其实有点问题,你能找到这个问题吗? diff --git a/README.md b/README.md index 0e82c8a..74ebbb5 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ * [超时设置](/30/timeout.py.md) * [Remote Webdriver](/31/remote.md) * [cookie与自动登陆](/32/cookie.py.md) +* [Expected Conditions与动态等待](/34/expected_conditions.py.md) ----------------------------------------------------------- diff --git a/expected_conditions.py b/expected_conditions.py new file mode 100644 index 0000000..2ee577a --- /dev/null +++ b/expected_conditions.py @@ -0,0 +1,58 @@ +#encoding:utf-8 +# example of how to use https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/support/expected_conditions.py + +from selenium import webdriver +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.common.by import By + +import unittest + +# dr = webdriver.PhantomJS('phantomjs') +dr = webdriver.Firefox() +# dr = webdriver.Chrome() +url = 'http://www.baidu.com' +search_text_field_id = 'kw' +dr.get(url) + +class ECExample(unittest.TestCase): + + def test_title_is(self): + ''' 判断title是否符合预期 ''' + title_is_baidu = EC.title_is(u'百度一下,你就知道') + self.assertTrue(title_is_baidu(dr)) + + def test_titile_contains(self): + ''' 判断title是否包含预期字符 ''' + title_should_contains_baidu = EC.title_contains(u'百度') + self.assertTrue(title_should_contains_baidu(dr)) + + def test_presence_of_element_located(self): + ''' 判断element是否出现在dom树 ''' + locator = (By.ID, search_text_field_id) + search_text_field_should_present = EC.visibility_of_element_located(locator) + + ''' 动态等待10s,如果10s内element加载完成则继续执行下面的代码,否则抛出异常 ''' + WebDriverWait(dr, 10).until(EC.presence_of_element_located(locator)) + WebDriverWait(dr, 10).until(EC.visibility_of_element_located(locator)) + + self.assertTrue(search_text_field_should_present(dr)) + + def test_visibility_of(self): + search_text_field = dr.find_element_by_id(search_text_field_id) + search_text_field_should_visible = EC.visibility_of(search_text_field) + self.assertTrue(search_text_field_should_visible('yes')) + + def test_text_to_be_present_in_element(self): + text_should_present = EC.text_to_be_present_in_element((By.NAME, 'tj_trhao123'), 'hao123') + self.assertTrue(text_should_present(dr)) + + + @classmethod + def tearDownClass(kls): + print 'after all test' + dr.quit() + print 'quit dr' + +if __name__ == '__main__': + unittest.main() diff --git a/expected_conditions.py.md b/expected_conditions.py.md new file mode 100644 index 0000000..ac169b4 --- /dev/null +++ b/expected_conditions.py.md @@ -0,0 +1,139 @@ +### 场景 + +Expected Conditions的使用场景有2种 +* 直接在断言中使用 +* 与WebDriverWait配合使用,动态等待页面上元素出现或者消失 + +### 方法注释 + +先翻译一下这些方法的用法 + +* ```title_is```: 判断当前页面的title是否精确等于预期 + +* ```title_contains```: 判断当前页面的title是否包含预期字符串 + +* ```presence_of_element_located```: 判断某个元素是否被加到了dom树里,并不代表该元素一定可见 + +* ```visibility_of_element_located```: 判断某个元素是否可见.**可见代表元素非隐藏,并且元素的宽和高都不等于0** + +* ```visibility_of```: 跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了 + +* ```presence_of_all_elements_located```: 判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是'column-md-3',那么只要有1个元素存在,这个方法就返回True + +* ```text_to_be_present_in_element```: 判断某个元素中的text是否**包含**了预期的字符串 + +* ```text_to_be_present_in_element_value```: 判断某个元素中的value属性是否**包含**了预期的字符串 + +* ```frame_to_be_available_and_switch_to_it```: 判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False + + +* ```invisibility_of_element_located```: 判断某个元素中是否不存在于dom树或不可见 + +* ```element_to_be_clickable```: 判断某个元素中是否可见并且是enable的,这样的话才叫clickable + +* ```staleness_of```: 等某个元素从dom树中移除,注意,这个方法也是返回True或False + +* ```element_to_be_selected```: 判断某个元素是否被选中了,一般用在下拉列表 + +* ```element_selection_state_to_be```: 判断某个元素的选中状态是否符合预期 + +* ```element_located_selection_state_to_be```: 跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator + +* ```alert_is_present```: 判断页面上是否存在alert,这是个老问题,很多同学会问到 + +### 具体的例子 + +例子的代码在[这里](https://gist.github.com/easonhan007/6dc544dc36367489c89f),并且是可以运行通过的。 + +下面的代码演示了一些常见疑问 + +* 如何等待页面上的某个元素出现,然后再对这个元素进行操作 +* 如何在unittest框架中所有的用例都共用1个浏览器实例,然后在全部用例结束后关闭浏览器 + +expected_conditions.py + +```python +#encoding:utf-8 +# example of how to use https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/support/expected_conditions.py + +from selenium import webdriver +from selenium.webdriver.support import expected_conditions as EC +from selenium.webdriver.support.wait import WebDriverWait +from selenium.webdriver.common.by import By + +import unittest + +# dr = webdriver.PhantomJS('phantomjs') +dr = webdriver.Firefox() +# dr = webdriver.Chrome() +url = 'http://www.baidu.com' +search_text_field_id = 'kw' +dr.get(url) + +class ECExample(unittest.TestCase): + + def test_title_is(self): + ''' 判断title是否符合预期 ''' + title_is_baidu = EC.title_is(u'百度一下,你就知道') + self.assertTrue(title_is_baidu(dr)) + + def test_titile_contains(self): + ''' 判断title是否包含预期字符 ''' + title_should_contains_baidu = EC.title_contains(u'百度') + self.assertTrue(title_should_contains_baidu(dr)) + + def test_presence_of_element_located(self): + ''' 判断element是否出现在dom树 ''' + locator = (By.ID, search_text_field_id) + search_text_field_should_present = EC.visibility_of_element_located(locator) + + ''' 动态等待10s,如果10s内element加载完成则继续执行下面的代码,否则抛出异常 ''' + WebDriverWait(dr, 10).until(EC.presence_of_element_located(locator)) + WebDriverWait(dr, 10).until(EC.visibility_of_element_located(locator)) + + self.assertTrue(search_text_field_should_present(dr)) + + def test_visibility_of(self): + search_text_field = dr.find_element_by_id(search_text_field_id) + search_text_field_should_visible = EC.visibility_of(search_text_field) + self.assertTrue(search_text_field_should_visible('yes')) + + def test_text_to_be_present_in_element(self): + text_should_present = EC.text_to_be_present_in_element((By.NAME, 'tj_trhao123'), 'hao123') + self.assertTrue(text_should_present(dr)) + + + @classmethod + def tearDownClass(kls): + print 'after all test' + dr.quit() + print 'quit dr' + +if __name__ == '__main__': + unittest.main() + +``` + +### 分析 +以title_is为例 + +```python +class title_is(object): + """An expectation for checking the title of a page. + title is the expected title, which must be an exact match + returns True if the title matches, false otherwise.""" + def __init__(self, title): + self.title = title + + def __call__(self, driver): + return self.title == driver.title +``` + +可以看到```title_is```实际上是1个class,其```__call__```方法被定义成是返回1个bool值。因此,一般的用法就是 + +```python +# 实例化 +the_instance = title_is('expected') +# 直接在实例上调用__call__ +the_instance(dr) #return True or False +``` From b527777931c812dd4ec67c208f5410869002b987 Mon Sep 17 00:00:00 2001 From: easonhan Date: Thu, 29 Sep 2016 13:40:49 +0800 Subject: [PATCH 05/11] fix issue' --- expected_conditions.py => 34/expected_conditions.py | 0 expected_conditions.py.md => 34/expected_conditions.py.md | 0 README.md | 1 + 3 files changed, 1 insertion(+) rename expected_conditions.py => 34/expected_conditions.py (100%) rename expected_conditions.py.md => 34/expected_conditions.py.md (100%) diff --git a/expected_conditions.py b/34/expected_conditions.py similarity index 100% rename from expected_conditions.py rename to 34/expected_conditions.py diff --git a/expected_conditions.py.md b/34/expected_conditions.py.md similarity index 100% rename from expected_conditions.py.md rename to 34/expected_conditions.py.md diff --git a/README.md b/README.md index 74ebbb5..68b3654 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ * [超时设置](/30/timeout.py.md) * [Remote Webdriver](/31/remote.md) * [cookie与自动登陆](/32/cookie.py.md) +* [切换窗口](/33/switch_window.py.md) * [Expected Conditions与动态等待](/34/expected_conditions.py.md) ----------------------------------------------------------- From cb454461c3c350e78846813e33e3990b4c1f1bbc Mon Sep 17 00:00:00 2001 From: easonhan Date: Thu, 29 Sep 2016 13:43:37 +0800 Subject: [PATCH 06/11] fix issue https://github.com/easonhan007/webdriver_guide/issues/6 --- 27/action.py.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/27/action.py.md b/27/action.py.md index 12b02cf..3850884 100644 --- a/27/action.py.md +++ b/27/action.py.md @@ -15,7 +15,7 @@ action * click_and_hold。鼠标左键点击住不放 * release。鼠标左键弹起,可以与click_and_hold配合使用 * move_to_element。把鼠标移动到元素的中心点 -* content_click。鼠标右键点击 +* context_click。鼠标右键点击 * drag_and_drop。拖拽 From ae44131d9deebb2364688542d36bd9d69a648d2b Mon Sep 17 00:00:00 2001 From: easonhan Date: Thu, 29 Sep 2016 14:21:47 +0800 Subject: [PATCH 07/11] add select --- 35/select.html | 30 ++++++++++++++++ 35/select.py | 33 ++++++++++++++++++ 35/select.py.md | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 4 files changed, 155 insertions(+) create mode 100644 35/select.html create mode 100644 35/select.py create mode 100644 35/select.py.md diff --git a/35/select.html b/35/select.html new file mode 100644 index 0000000..bfbc403 --- /dev/null +++ b/35/select.html @@ -0,0 +1,30 @@ + + + + Select + + + + + +
+

Select

+
+
+
+ + +
+ +
+
+
+ + + diff --git a/35/select.py b/35/select.py new file mode 100644 index 0000000..526522b --- /dev/null +++ b/35/select.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +from selenium import webdriver +from selenium.webdriver.support.select import Select +from time import sleep +import os + +dr = webdriver.Firefox() +file_path = 'file:///' + os.path.abspath('select.html') +dr.get(file_path) + +phone_selector = Select(dr.find_element_by_tag_name('select')) + +# 返回所有的options +print(phone_selector.options) +sleep(1) + +# 返回所有选中的options +print(phone_selector.all_selected_options) +sleep(1) + +# 通过option的value值来选择iphone 7 +phone_selector.select_by_value('ip7') +sleep(2) + +# 通过index来选择,比如选择第2项 +phone_selector.select_by_index(1) +sleep(1) + +# 通过option的text来选择 +phone_selector.select_by_visible_text('iPhone 6s') + + +dr.quit() diff --git a/35/select.py.md b/35/select.py.md new file mode 100644 index 0000000..e7ead91 --- /dev/null +++ b/35/select.py.md @@ -0,0 +1,91 @@ +# Select + +### 场景 + +在处理下拉框(select)的时候selenium给我们提供了一系列的便捷方法,我们只需要使用```selenium.webdriver.support.select.Select```类来稍微封装一下就好了。 + +源代码在(这里)[https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/support/select.py] + +下面是我们经常会用到的一些方法 + +* options: 返回下拉框里所有的选项 +* all_selected_options: 返回所有选中的选项 +* select_by_value(value): 通过option的value值来选择 +* select_by_index(index) 通过option的顺序来选择 +* select_by_visible_text(text): 通过option的text来选择 + + +### 代码 + +select.html + +```html + + + + Select + + + + + +
+

Select

+
+
+
+ + +
+ +
+
+
+ + + +``` + +select.py + +```python + +# -*- coding: utf-8 -*- +from selenium import webdriver +from selenium.webdriver.support.select import Select +from time import sleep +import os + +dr = webdriver.Firefox() +file_path = 'file:///' + os.path.abspath('select.html') +dr.get(file_path) + +phone_selector = Select(dr.find_element_by_tag_name('select')) + +# 返回所有的options +print(phone_selector.options) +sleep(1) + +# 返回所有选中的options +print(phone_selector.all_selected_options) +sleep(1) + +# 通过option的value值来选择iphone 7 +phone_selector.select_by_value('ip7') +sleep(2) + +# 通过index来选择,比如选择第2项 +phone_selector.select_by_index(1) +sleep(1) + +# 通过option的text来选择 +phone_selector.select_by_visible_text('iPhone 6s') + +dr.quit() +``` diff --git a/README.md b/README.md index 68b3654..5d3dfdd 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ * [cookie与自动登陆](/32/cookie.py.md) * [切换窗口](/33/switch_window.py.md) * [Expected Conditions与动态等待](/34/expected_conditions.py.md) +* [处理下拉框](/35/select.py.md) ----------------------------------------------------------- From 6d222fb28e662ca6216a333c8089819bd32a9836 Mon Sep 17 00:00:00 2001 From: easonhan Date: Thu, 29 Sep 2016 14:23:22 +0800 Subject: [PATCH 08/11] fix markdown issue --- 35/select.py.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/35/select.py.md b/35/select.py.md index e7ead91..57066e2 100644 --- a/35/select.py.md +++ b/35/select.py.md @@ -4,7 +4,7 @@ 在处理下拉框(select)的时候selenium给我们提供了一系列的便捷方法,我们只需要使用```selenium.webdriver.support.select.Select```类来稍微封装一下就好了。 -源代码在(这里)[https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/support/select.py] +源代码在[这里](https://github.com/SeleniumHQ/selenium/blob/master/py/selenium/webdriver/support/select.py) 下面是我们经常会用到的一些方法 From af791f9d6052deaefe4c61421c0561a679a3f365 Mon Sep 17 00:00:00 2001 From: easonhan Date: Thu, 29 Sep 2016 14:53:09 +0800 Subject: [PATCH 09/11] update gitbook --- SUMMARY.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/SUMMARY.md b/SUMMARY.md index 49899d9..d230bf8 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -166,3 +166,12 @@ * [python篇](32/cookie.py.md) * [Ruby篇](32/cookie.md) * [Java篇](32/cookie.java.md) + +* 33: 切换窗口 + * [python篇](33/switch_window.py.md) + +* 34: Expected Conditions与动态等待 + * [python篇](34/expected_conditions.py.md) + +* 35: 处理下拉框 + * [python篇](35/select.py.md) From fe7ef888371de8c9563d72df812d9781a1e4a1a1 Mon Sep 17 00:00:00 2001 From: easonhan Date: Wed, 19 Oct 2016 19:30:09 +0800 Subject: [PATCH 10/11] Update README.md --- README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/README.md b/README.md index 5d3dfdd..11ea7a7 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,9 @@ 几年前我在github上写了webdriver实用指南,由于github本身设计的目的是为了承载代码,而不是承载书籍,用户观感不佳,所以现在将其重构至gitbook。 -[gitbook地址](https://easonhan007.gitbooks.io/selenium-webdriver/content/),看着会舒服点。 我的blog是[乙醇的blog](http://www.cnblogs.com/nbkhic) -如果你自学困难,想要找人辅导,与一群小伙伴一同学习的话,你可以看一下[我们的课程](http://itest.info/courses) - ## 内容预览 ### python篇 From 5d9224743ea687c0b3ca201fc3fbd2d2b5a6e488 Mon Sep 17 00:00:00 2001 From: easonhan Date: Sun, 27 Nov 2016 14:02:26 +0800 Subject: [PATCH 11/11] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 11ea7a7..3c58f41 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # 简介 -几年前我在github上写了webdriver实用指南,由于github本身设计的目的是为了承载代码,而不是承载书籍,用户观感不佳,所以现在将其重构至gitbook。 +几年前我在github上写了webdriver实用指南,由于github本身设计的目的是为了承载代码,而不是承载书籍,用户观感不佳,所以现在将其重构至[gitbook](https://www.gitbook.com/book/easonhan007/selenium-webdriver/details)。 我的blog是[乙醇的blog](http://www.cnblogs.com/nbkhic)