《一头扎进》系列之Python+Selenium框架设计篇2- 价值好几K的框架,不看白不看,看了还想看
<h3>1. 简介</h3><p> 上一篇介绍了自动化框架的架构,今天宏哥就带领小伙伴或者童鞋们开始开工往这个框架里开始添砖加瓦。主要是介绍一个框架unittest单元测试框架和一种设计思想POM。</p>
<h3 class="title-article">2. unittest单元测试框架</h3>
<p>前面文章已经简单介绍了一些关于自动化测试框架的介绍,知道了什么是自动化测试框架,主要有哪些特点,基本组成部分等。在继续介绍框架设计之前,我们先来学习一个工具,叫unittest。</p>
<p> unittest是一个单元测试框架,是Python编程的单元测试框架。有时候,也做叫做“PyUnit”,是Junit的Python语言版本。这里了解下,Junit是Java语言的单元测试框架,Java还有一个很好用的单元测试框架叫TestNG,本系列只学习Python,所以只需要unittest是</p>
<p>Python里的一个单元测试框架就可以了。</p>
<p> unittest支持测试自动化,共享测试用例中的初始化和关闭退出代码,在unittest中最小单元是test,也就是一个测试用例。要了解unittest单元测试框架,先来了解以下几个重要的概念。</p>
<h4>2.1 测试固件(test fixture)</h4>
<p> 一个测试固件包括两部分,执行测试代码之前的准备部分和测试结束之后的清扫代码。这两部分一般用函数setUp()和tearDown()表示。这里举例以下,例如要测试百度搜索selenium这个场景,我们的测试固件可以这样写,setUp()里写打开浏览器,浏览器最大</p>
<p>化,和打开百度首页等脚本代码;在tearDown()里写结束搜索后,退出并关闭浏览器的代码。</p>
<h4>2.2 测试用例(test case)</h4>
<p> unittest中管理的最小单元是测试用例,一个测试用例,包括测试固件,和具体测试业务的函数或者方法。一个测试用例中,测试固件可以不写,但是至少有一个已test开头的函数。unittest会自动化识别test开头的函数是测试代码,如果你写的函数不是test开头,</p>
<p>unittest是不会执行这个函数里面的脚本的,这个千万要记住,所有的测试函数都要test开头,记住是小写的哦。</p>
<h4>2.3 测试套件 (test suite)</h4>
<p> 很简单,就是很多测试用例的集合,叫测试套件,一个测试套件可以随意管理多个测试用例。如果测试用例比作单个学生,测试套件就是好像是班级的概念。</p>
<h4>2.4 测试执行器 (test runner)</h4>
<p> test runner是一个用来执行加载测试用例,并执行用例,且提供测试输出的一个组建。test runner可以加载test case或者test suite进行执行测试任务。</p>
<p>我们举例来,练习一下test fixture和test case的使用,学习unittest的简单用法:</p>
<h4>2.5 设计思路</h4>
<p>1. 新建一个testbaidu.py的文件</p>
<p>2. 导入unittest模块</p>
<p>3. 当前测试类继承unittest.TestCase,相当于当前利用unittest创建了一个test case,这个test case是能够被unittest直接识别。</p>
<p>4. 写setUP(),主要是打开浏览器和打开站点</p>
<p>5. 写一个test_search()用例写搜索的代码</p>
<p>6. 写tearDown(),主要是浏览器退出操作</p>
<p>相关脚本代码如下:</p>
<h5>2.5.1 代码实现:</h5>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191218113041947-2113459901.png" alt=""></p>
<h5>2.5.2 参考代码:</h5>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> coding=utf-8🔥</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 2.注释:包括记录创建时间,创建人,项目名称。</span>
<span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">
Created on 2019-12-18
@author: 北京-宏哥 QQ交流群:705269076
Project: 《《一头扎进》系列之Python+Selenium框架设计篇2- 价值好几K的框架,不看别后悔,过时不候
</span><span style="color: rgba(128, 0, 0, 1)">'''</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 3.导入模块</span>
<span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> time
</span><span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> unittest
</span><span style="color: rgba(0, 0, 255, 1)">from</span> selenium <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> webdriver
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BaiduSearch(unittest.TestCase):
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> setUp(self):
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
测试固件的setUp()的代码,主要是测试的前提准备工作
:return:
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
self.driver </span>=<span style="color: rgba(0, 0, 0, 1)"> webdriver.Chrome()
self.driver.maximize_window()
self.driver.implicitly_wait(</span>8<span style="color: rgba(0, 0, 0, 1)">)
self.driver.get(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://www.baidu.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> tearDown(self):
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
测试结束后的操作,这里基本上都是关闭浏览器
:return:
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
self.driver.implicitly_wait(</span>8<span style="color: rgba(0, 0, 0, 1)">)
self.driver.quit()
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_baidu_search(self):
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
这里一定要test开头,把测试逻辑代码封装到一个test开头的方法里。
:return:
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
self.driver.find_element_by_id(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">kw</span><span style="color: rgba(128, 0, 0, 1)">'</span>).send_keys(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">selenium</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
time.sleep(</span>1<span style="color: rgba(0, 0, 0, 1)">)
self.driver.find_element_by_id(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">su</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">).click()
time.sleep(</span>3<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 0, 255, 1)">assert</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">selenium</span><span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> self.driver.title
</span><span style="color: rgba(0, 0, 255, 1)">print</span> (<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Test Pass.</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">except</span><span style="color: rgba(0, 0, 0, 1)"> Exception as e:
</span><span style="color: rgba(0, 0, 255, 1)">print</span> (<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Test Fail.</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, format(e))
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
unittest.main()</span></pre>
</div>
<h5>2.5.3 运行结果:</h5>
<p>运行代码后,控制台打印如下图的结果</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191218113456097-1885317626.png" alt=""></p>
<p>解释:<br> 最后结尾处的unittest.main(),添加这个是支持在cmd,里面,cd到这个脚本文件所在的目录,然后python 脚本名.py执行,如果不添加这一段,是无法执行cmd里面运行脚本的,在PyCharm中,不添加最后一段,也可以通过,右键 Run "unittest xxx",来达到执行效果。</p>
<h3 class="title-article">3. 什么是POM(Page Object Model)</h3>
<p> 前面我们介绍了Python中的单元测试框架unittest,以后我们所有的测试类文件,都采用unittest来辅助我们进行debug和脚本开发。搞定了debug机制和确定了unittest来进行创建和管理我们的自动化测试脚本,接下来我们来考虑下,框架设计中一种很普遍的设计</p>
<p>思想-POM(Page Object Model)。</p>
<div>
<div>
<h4>3.1 POM是什么</h4>
<p>
Page Object Model (POM) 直译为“页面对象模型”,这种设计模式旨在为每个待测试的页面创建一个页面对象(class),将那些繁琐的定位操作封装到这个页面对象中,只对外提供必要的操作接口。</p>
<h4>3.2 POM 有什么好处</h4>
<p>
POM 将页面定位和业务操作分开,分离了测试对象和测试脚本,如果UI更改页面,测试脚本不需要更改,只需要更改页面对象中的某些代码就可以,提高了可维护性。</p>
</div>
</div>
<p> POM,中文字母意思是,页面对象模型,POM是一种最近几年非常流行的自动化测试模型,或者思想,POM不是一个框架,就是一个解决问题的思想。采用POM的目的,是为了解决前端中UI变化频繁,从而造成测试自动化脚本维护的成本越来越大。下图,形</p>
<p>象描述了POM的好处。</p>
<p> <img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191218114227700-1160101342.png" alt=""></p>
<p> 从上图看出,采取了POM设计思路和不采取的区别,左侧把测试代码和页面元素都写在一个类文件,如果需要更改页面,那么就要修改页面元素定位,从而要修改这个类中测试代码,这个看起来和混乱。右侧,采取POM后,主要的区别就是,把页面元素和业务</p>
<p>逻辑和测试脚本分离出来到两个不同类文件。ClassA只写页面元素定位,和业务逻辑代码操作的封装,ClassB只写测试脚本,不关心如何元素定位,只写调用ClassA的代码去覆盖不同的测试场景。如果前端页面发生变化,只需要修改ClassA的元素定位,而不需要去</p>
<p>修改ClassB中的测试脚本代码。</p>
<p>POM主要有以下优点:</p>
<p>1. 把web ui对象仓库从测试脚本分离,业务代码和测试脚本分离。</p>
<p>2. 每一个页面对应一个页面类,页面的元素写到这个页面类中。</p>
<p>3. 页面类主要包括该页面的元素定位,和和这些元素相关的业务操作代码封装的方法。</p>
<p>4. 代码复用,从而减少测试脚本代码量。</p>
<p>5. 层次清晰,同时支持多个编写自动化脚本开发,例如每个人写哪几个页面,不影响他人。</p>
<p>6. 建议页面类和业务逻辑方法都给一个有意义的名称,方便他人快速编写脚本和维护脚本。</p>
<h4>3.3 牛刀小试</h4>
<div>
<div>
<p>比如测试一个登陆页面:新浪微博 ,执行测试的人员传递不同的数据到帐号、密码框就可以了,而不应该去顾虑:页面是否已经加载完成?怎样定位到帐号输入框?怎样定位到登陆按钮等等问题。</p>
<p>这些问题全部交由登陆页面的“页面对象”去解决并封装起来,只提供给测试人员三个接口方法:1.帐号输入接口、2.密码输入接口、3.提交接口。</p>
<p>首先定义一个基本页面 BasePage类 ,定义基本的页面操作,提供给其他页面去继承,basePage.py 内容如下:</p>
</div>
<h5>3.3.1 代码实现:</h5>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191218134511218-2077873814.png" alt=""></p>
<h5>3.3.2 参考代码:</h5>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> coding=utf-8🔥</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 2.注释:包括记录创建时间,创建人,项目名称。</span>
<span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">
Created on 2019-12-18
@author: 北京-宏哥 QQ交流群:705269076
Project: 《《一头扎进》系列之Python+Selenium框架设计篇2- 价值好几K的框架,不看别后悔,过时不候
</span><span style="color: rgba(128, 0, 0, 1)">'''</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 3.导入模块</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> selenium <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> webdriver
</span><span style="color: rgba(0, 0, 255, 1)">from</span> selenium.webdriver.support.wait <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> WebDriverWait
</span><span style="color: rgba(0, 0, 255, 1)">from</span> selenium.webdriver.support <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> expected_conditions as EC
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BasePage(object):
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
基础页面,提供给其他页面继承
</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
<span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self, driver, base_url, title):
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
初始化
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
self.driver </span>=<span style="color: rgba(0, 0, 0, 1)"> driver
self.base_url </span>=<span style="color: rgba(0, 0, 0, 1)"> base_url
self.title </span>=<span style="color: rgba(0, 0, 0, 1)"> title
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> _open(self, url):
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
私有方法,打开url参数指定的页面,
并检查打开是否正确
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
self.driver.get(url)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 显式等待10秒,如果打开页title与预期不符或者超时,抛出异常</span>
WebDriverWait(self.driver, 10<span style="color: rgba(0, 0, 0, 1)">).until(EC.title_is(self.title))
</span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> open(self):
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
公共方法,调用私有方法_open()打开链接
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
self._open(self.base_url)
</span><span style="color: rgba(0, 0, 255, 1)">def</span> find_element(self, *<span style="color: rgba(0, 0, 0, 1)">loc):
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
定位指定元素
</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 显式等待元素,超过10秒未找到则抛出超时异常(TimeoutException)</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> presence_of_element_located: 不关心元素是否可见,只关心元素是否存在在页面中</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> visibility_of_element_located: 不仅找到元素,并且该元素必须可见</span>
WebDriverWait(self.driver, 15<span style="color: rgba(0, 0, 0, 1)">).until(EC.visibility_of_element_located(loc))
</span><span style="color: rgba(0, 0, 255, 1)">return</span> self.driver.find_element(*<span style="color: rgba(0, 0, 0, 1)">loc)
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
driver </span>=<span style="color: rgba(0, 0, 0, 1)"> webdriver.Chrome()
driver.maximize_window()
page </span>= BasePage(driver, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">https://www.baidu.com/</span><span style="color: rgba(128, 0, 0, 1)">','百度一下,你就知道'</span><span style="color: rgba(0, 0, 0, 1)">)
page.open()
driver.quit()</span></pre>
</div>
<h5>3.3.3 运行结果:</h5>
<p>运行代码后,控制台打印如下图的结果</p>
<img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191218142048727-708281067.png" alt=""><br><br>再定义一个 LoginPage类 继承 BasePage类 ,向外提供测登陆方法。文件命名为 xl_login.py ,内容如下:</div>
<div>
<h5>3.3.4 代码实现:</h5>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191218141704612-561512086.png" alt=""></p>
<h5>3.3.5 参考代码:</h5>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> coding=utf-8🔥</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 2.注释:包括记录创建时间,创建人,项目名称。</span>
<span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">
Created on 2019-12-18
@author: 北京-宏哥 QQ交流群:705269076
Project: 《《一头扎进》系列之Python+Selenium框架设计篇2- 价值好几K的框架,不看别后悔,过时不候
</span><span style="color: rgba(128, 0, 0, 1)">'''</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 3.导入模块</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> selenium <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> webdriver
</span><span style="color: rgba(0, 0, 255, 1)">from</span> selenium.webdriver.common.by <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> By
</span><span style="color: rgba(0, 0, 255, 1)">from</span> basePage <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> BasePage
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> LoginPage(BasePage):
</span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
新浪微薄登陆页面
继承自基础页面BasePage
</span><span style="color: rgba(128, 0, 0, 1)">"""</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 定位帐号输入框</span>
username_loc = (By.ID, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">loginname</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 定位密码输入框</span>
password_loc = (By.NAME, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">password</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 定位登陆按钮</span>
submit_loc = (By.XPATH, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">.//*[@id="pl_login_form"]/div/div/div/a</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 定位提示信息,如:请输入验证码</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 不要迷信开发者工具提供的Xpath,</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 比如这里提供的Xpath://*[@id="layer_15582553868501"]/div/p/span,</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> id是动态的,无法使用,需自行推到Xpath</span>
message_loc = (By.XPATH, <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">//div[@class="content layer_mini_info"]/p/span</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 输入用户名操作</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> type_username(self, username):
self.find_element(</span>*<span style="color: rgba(0, 0, 0, 1)">self.username_loc).send_keys(username)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 输入密码操作</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> type_password(self, password):
self.find_element(</span>*<span style="color: rgba(0, 0, 0, 1)">self.password_loc).send_keys(password)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 点击登陆按钮操作</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> submit(self):
self.find_element(</span>*<span style="color: rgba(0, 0, 0, 1)">self.submit_loc).click()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 获取提示信息</span>
<span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get_message(self):
</span><span style="color: rgba(0, 0, 255, 1)">return</span> self.find_element(*<span style="color: rgba(0, 0, 0, 1)">self.message_loc).text
</span><span style="color: rgba(0, 0, 255, 1)">if</span> <span style="color: rgba(128, 0, 128, 1)">__name__</span> == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">__main__</span><span style="color: rgba(128, 0, 0, 1)">'</span>:<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 测试登陆</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 预打开页面</span>
base_url = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">https://weibo.com/</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 页面title</span>
title = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">微博-随时随地发现新鲜事</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 准备好待输入的用户名和密码</span>
username = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">haha</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
password </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">hehe</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打开Chrome浏览器</span>
driver =<span style="color: rgba(0, 0, 0, 1)"> webdriver.Chrome()
driver.maximize_window()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 登陆页面初始化</span>
login =<span style="color: rgba(0, 0, 0, 1)"> LoginPage(driver, base_url, title)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打开新浪微博页</span>
<span style="color: rgba(0, 0, 0, 1)"> login.open()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 输入用户名</span>
<span style="color: rgba(0, 0, 0, 1)"> login.type_username(username)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 输入密码</span>
<span style="color: rgba(0, 0, 0, 1)"> login.type_password(password)
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 点击登陆</span>
<span style="color: rgba(0, 0, 0, 1)"> login.submit()
</span><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 打印提示信息</span>
<span style="color: rgba(0, 0, 255, 1)">print</span>(login.get_message())</pre>
</div>
<h5>3.3.6 运行结果:</h5>
<p>运行代码后,控制台打印如下图的结果</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191218141558260-772367539.png" alt=""></p>
</div>
<h3>4.小结</h3>
<p>好了,今天的分享就到这里吧!!!谢谢各位的耐心阅读。有问题加群交流讨论</p>
<p> </p>
<p style="text-align: center"><span style="font-size: 14pt">您的肯定就是我进步的动力。如果你感觉还不错,就请鼓励一下吧!记得随手点波<strong> <span style="font-size: 18pt; color: rgba(255, 0, 0, 1)">推荐</span> 不</strong>要忘记哦!!!</span></p>
<p style="text-align: center"><span style="font-size: 14pt">别忘了点<strong><span style="font-size: 18pt; color: rgba(255, 0, 0, 1)">推荐</span></strong>留下您来过的痕迹</span></p>
<p style="text-align: center"><span style="font-size: 14pt"> </span></p>
<p><span style="font-size: 14pt"><img style="display: block; margin-left: auto; margin-right: auto" src="https://img2018.cnblogs.com/blog/1232840/201908/1232840-20190816135641371-1314831001.gif" alt=""></span></p>
</div>
<div id="MySignature" role="contentinfo">
<div id="MySignature" style="display: block">
<div style="font-size: 13px; border: 1px dashed rgb(45, 161, 45); padding: 10px 15px; background-color: rgb(248, 248, 248)">
<label style="font-weight: bold">
为了方便大家在移动端也能看到我分享的博文,现已注册个人微信公众号,扫描左下方二维码即可,欢迎大家关注,提前解锁更多测试干货!有时间会及时分享相关技术博文。
</label>
<br>
<label style="font-weight: bold">
为了方便大家互动讨论相关技术问题,刚刚建立了咱们的专门的微信群交流互动群,群内会分享交流测试领域前沿知识。请您扫描中间的微信二维码进群
</label>
<br>
<label style="font-weight: bold">
为了方便大家互动讨论相关技术问题,现已组建专门的微信群,由于微信群满100,请您扫描右下方宏哥个人微信二维码拉你进群
<label style="font-weight: bold; color: red; font-size: 15px">
(请务必备注:已关注公众号进群)平时上班忙(和你一样),所以加好友不及时,请稍安勿躁~
</label>
,欢迎大家加入这个大家庭,我们一起畅游知识的海洋。
</label>
<br>
感谢您花时间阅读此篇文章,如果您觉得这篇文章你学到了东西也是为了犒劳下博主的码字不易不妨打赏一下吧,让博主能喝上一杯咖啡,在此谢过了!
<br>
如果您觉得阅读本文对您有帮助,请点一下左下角
“推荐”
按钮,您的
<label style="font-weight: bold; color: red; font-size: 15px">
“推荐”
</label>
将是我最大的写作动力!另外您也可以选择
【
<strong>
关注我
</strong>
】
,可以很方便找到我!
<br>
本文版权归作者和博客园共有,来源网址:
https://www.cnblogs.com/du-hong
欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利!
</div>
<div style="text-align: center; margin-top: 10px">
<p style=" font-weight: bolder; color: red; ">
公众号(关注宏哥)     
        
       
       
微信群(扫码进群)    
       
       
    
      
      客服微信
</p>
<img style="width: 200px;padding-right: 50px;" alt="个人微信公众号" src="https://img2018.cnblogs.com/common/1741949/201911/1741949-20191119095948011-608816619.png">
<img style="width: 200px;padding-right: 65px;" alt="微信群" src="https://img2024.cnblogs.com/blog/1232840/202506/1232840-20250610113707419-637869921.png">
<img style="width: 200px" alt="个人微信" src="https://img2018.cnblogs.com/common/1741949/201911/1741949-20191106101257091-849954564.png">
</div>
</div><br><br>
来源:https://www.cnblogs.com/du-hong/p/12058673.html
頁:
[1]