Selenium自动化测试

Selenium自动化测试

 

课程目标:

  1. Selenium自动化测试基础和环境部署
  2. 单元测试框架
  3. 元素定位
  4. WebDriver API
  5. 项目实战

 

今天的课程:Selenium自动化测试基础和环境部署

 

  1. 自动化测试简介

1)         什么是自动化测试

自动化测试是相对于手工测试而言的。

  • 手工测试:指的是由我们的测试人员一个一个的去执行我们的测试用例,通过键盘鼠标输入一些数据做一些操作,查看系统的实际运行结果跟用例上的预期结果是否相符的过程。
  • 自动化测试:指的是把以人为驱动的测试转化成机器(工具)执行的一个过程。

2)         自动化测试的目标(为什么要做自动化测试)

(1)       减少了手工测试中的重复性工作

(2)       提高了测试用例的执行效率

(3)       可以节省企业的人力成本

(4)       可用于在线产品的运行状态的监控

(5)       可用于大量测试数据的生成

(6)       有些测试手工很难实现(实现成本很高)

3)         自动化测试的优缺点

优点:

(1)       快速高效:

(2)       可靠:

(3)       可重复适用:

(4)       可以执行一些手工测试困难或不可能进行的测试

(5)       使得系统的回归测试变得更加的方便

……

                   缺点:

(1)       工具本身没有想象力,无法进行主观判断,例如界面的色彩和布局等,这些工具无法判断;

(2)       技术门槛相对较高:需要你会写代码、懂一些开发;

(3)       自动化测试的开发和维护成本更高;

(4)       自动化测试工具本身是一个产品,产品会有局限性

……

4)         自动化测试的分类

(1)       传统分类:功能自动化测试和性能自动化测试

  • 常见的功能自动化测试工具:Selenium、Appium、UFT(QTP)……
  • 常见的性能自动化测试工具:Jmeter、LoadRunnur(LR)

(2)       分层的自动化测试:

单元自动化测试——》接口自动化测试——》UI自动化测试

  • 单元自动化测试:单元测试指的是对软件中最小可测单元进行检查和验证。规范的单元测试需要借助单元测试框架来进行。主流的语言都有相应的单元测试框架。
  • 接口自动化测试:针对模块间的调用与返回;浏览器和服务器的接口以及外部接口
  • UI自动化测试:(User Interface 用户界面),针对用户使用的界面进行的测试。(Selenium)

5)         自动化测试的适用场景

并不是所有的项目都适合开展自动化测试,自动化测试适用于在需要重复执行机械化的界面操作、计算、数值比较、搜索等方面,实现更加快速的回归测试,提高测试的效率。

一般来讲,需要满足三个条件才会考虑开展自动化测试:

(1)       软件的需求变动不频繁

折中的办法:对系统中相对稳定的模块做自动化测试,对变动较大的部分做手工测试。

(2)       项目的周期足够长

(3)       自动化测试脚本可重复使用

6)         自动化测试的流程

测试计划——》测试设计(测试环境搭建+测试用例的设计+编写测试脚本)——》测试实施(有一部分的测试用例是通过运行测试脚本的方式来执行)——》测试总结

 

7)         关于自动化测试几个误解

  • 自动化测试可以完全代替手工测试吗?不可以。
  • 自动化测试可以发现更多新的bug吗?不可以。自动化测试本身的作用不是用来发现新的bug的,而是用来验证以前能够正常工作的功能是否依旧可以正常工作。自动化测试可以大大的降低手工测试的重复性,更适用于回归测试。
  • 自动化测试是万能的吗?不是。

手工测试不可被替代的几点原因:

(1)       测试用例的设计:测试人员的经验和对错误的猜测能力是工具不可替代的;

(2)       界面和用户体验测试:人类的审美观和心理体验是工具不可模拟的;

(3)       正确性的检验:人们对是非的判断,逻辑推理能力是工具不具备的。

8)         Selenium自动化测试工具的介绍

(1)       什么是Selenium

Selenium是专门为Web应用程序编写的一个验收测试工具,它的主要功能包括两个方面:

  • 测试Web应用程序看它是否可以很好的工作在不同的浏览器和操作系统之上(兼容性测试)
  • 测试Web应用程序的功能,创建回归测试检验软件的功能和用户需求

Selenium的特点:

  • 开源免费
  • 多浏览器支持:Firefox、Chrome、Opera、Edge…
  • 多平台支持:Linux、Windows、Mac…
  • 多语言支持:Java、Python、JS、C++…
  • 对Web页面有良好的支持
  • 简单、灵活…
  • 支持分布式测试用例执行

……

 

(2)       Selenium的历史

经历了三个版本:

  • Selenium1:2004 基于JS代码库写了这个工具,做网页测试
  • Selenium2:2008合并=Selenium1+WebDriver,我们常常看到的Selenium WebDriver,简称为WebDriver。
  • Selenium3:2016

(3)       Selenium的组成

  • Selenium IDE:Firefox的插件,实现了简单的浏览器操作的录制与回放。由于这个模式存在诸多局限,目前已经停止维护。
  • Selenium Grid:自动化测试的辅助工具,可用于实现在多个测试环境以并发的方式执行测试脚本,从而缩短测试脚本的执行时间
  • Selenium RC(Remote Control):是Selenium1的核心部分

RC又分为两个部分:Client Libraries 和Selenium Server

Client Libraries:主要用来编写测试脚本

Selenium Server:负责控制浏览器的行为

Selenium3去掉了RC功能

  • Selenium WebDriver:是Selenium2和3的核心部分,是RC的替代品。通过原生浏览器的驱动直接去控制浏览器。

 

9)         自动化测试中编程语言的选择

软件开发的时候使用的编程语言跟自动化测试使用的编程语言之间没有必然的联系。假设公司使用的是Java,你仍然可以使用Python做自动化测试。

  1. 环境部署

步骤如下:

1)         安装Python和PyCharm

2)         安装Selenium:pip install selenium

检查是否安装成功:进入Python交互环境,输入import selenium不报错即安装成功

3)         安装浏览器并禁用更新

4)         获取浏览器对应驱动,并将驱动路径添加到系统环境变量path里;

5)         第一个示例:启动浏览器,打开百度首页,在搜索框输入Selenium,点击搜索按钮,关闭浏览器。

from selenium import webdriver

from time import sleep

 

browser=webdriver.Firefox()

sleep(2)

browser.get("http://www.baidu.com")

sleep(2)

browser.find_element_by_id("kw").send_keys("Selenium")

sleep(2)

browser.find_element_by_id("su").click()

sleep(2)

browser.quit()

 

回顾:环境部署过程

1)         安装Python和PyCharm

2)         安装Selenium包

在线安装:pip install selenium

离线安装:依次进入urllib3和selenium包下,执行命令:python setup.py install

3)         安装浏览器(禁用自动更新)

4)         准备好浏览器的驱动,并将驱动路径添加到系统环境变量path里

5)         第一个自动化实例

 

 

今天的课程:单元测试框架

 

不同的编程语言有不同的单元测试框架。Python语言有很多的单元测试框架和工具:doctest\unittest\pytest\nose等。Unittest是Python语言自带的单元测试框架。

 

  1. Web自动化测试为什么要学单元测试框架?

Web自动化测试通常使用单元测试框架去完成测试用例的编写、组织与执行,预期结果和实际结果的比较(断言)以及测试结果的生成。

单元测试框架主要做了3件事情:

1)         提供了测试用例的组织与执行

2)         提供了丰富的断言方法

3)         提供了丰富的日志信息

 

  1. 什么是框架?

Framework,指的是为了解决一个或者是一类问题而开发的产品,用户只需要调用它所提供的类或函数,就可以实现它所定义的功能。

Unittest框架它主要实现了测试用例的组织与执行以及测试结果的生成。

 

  1. 不用单元测试框架可以写单元测试吗?

可以

from calculator import Count

 

class TestCount:

 

    def test_add(self):

        try:

            c=Count(1,2)

            s=c.add()

            assert s==2,'test failed,not equal'

        except AssertionError as msg:

            print(msg)

        else:

            print('test passed!')

 

mytest=TestCount()

mytest.test_add()

注解:

  • assert语句的语法格式:assert 表达式,’报错信息’——》判断表达式是否成立,如果成立,则测试通过,如果不成立,则抛出异常错误,给出后面的报错信息。
  • 以上这种测试方法的编写存在的问题:

ü  由于没有一定的规范可以遵循,不同的人写出来的测试代码可能不同,不统一的代码维护起来很麻烦

ü  需要编写大量的辅助代码才能进行单元测试

为了让我们的单元测试代码更容易编写和维护,单元测试框架就出现了!

 

  1. 如果使用单元测试框架,如何写单元测试

import unittest

from calculator import Count

 

class TestCount(unittest.TestCase):

 

    def setUp(self) -> None:

        print('test start...')

 

    def test_add(self):

        print('test is in progressing...')

        c=Count(1,2)

        self.assertEqual(c.add(),3)

 

    def tearDown(self) -> None:

        print('test end...')

 

       

if __name__=='__main__':

unittest.main()

 

注解:

  • class TestCount(unittest.TestCase):——》使用unittest写单元测试时,创建的测试类必须继承unittest的TestCase类
  • setUp()方法用于测试用例执行前的初始化工作,tearDown()方法用于测试用例执行后的清理工作,以test打头的方法称为测试方法,在测试方法里,不再使用烦琐的异常处理,而是使用unittest提供的assertEqual()断言
  • setUp()方法在每一次测试方法(以test打头的方法)被调用之前都会被执行,tearDown()方法在每一次测试方法被调用之后都会被执行。这也就是说,当有两个测试方法的时候,setUp()执行两次,tearDown()执行两次。
  • unittest.main()——》unittest提供了main()方法,它可以自己去搜索所有包含在当前模板的所有以test打头的测试方法,并自动执行它们
  • 使用unittest组织的单元测试里,可以自动执行的方法有:setUp(),teardown(),以test打头的方法,除此以外的其他方法,如a,b等,不会自动执行。
  • if __name__=='__main__':——》如果你希望if __name__=='__main__':下的语句块得到执行,那么你必须运行这个文件本身。——》testcount1.py文件既可以用来直接运行,也可以用来作为一个模块导入运行,那么它下面的语句块在自己直接运行的时候会被执行,被当作模块导入的时候不会被执行。

 

  1. unittest的相关概念及使用

1)         unittest里的4个重要概念

  • test case:测试用例,unittest提供了TestCase类用于创建测试用例。测试用例指的是一个完整的测试流程/单元,包括测试前的准备工作,测试过程以及测试后的清理工作
  • test suite:测试套件/集合,将多条测试用例组织在一起执行,就产生了测试套件的概念。test suite可以用来组装测试用例
  • test runner:测试运行器,用来执行设定的测试用例和将测试结果提供给用户
  • test fixture:测试固件,一个test fixture代表一个或多个测试执行前的准备工作和测试结束后的清理工作

 

2)         单元测试加载的两种方式:

  • 直接通过unittest.main()方法来加载所有的测试用例进行执行;
  • 将所有的测试用例添加到测试套件里,然后使用测试运行器去执行。

 

import unittest

from calculator import Count

 

class TestCount(unittest.TestCase):

 

    def setUp(self) -> None:

        print('test start...')

 

    def test_add1(self):

        print('test1 is in progressing...')

        c=Count(1,2)

        self.assertEqual(c.add(),3)

 

    def test_add2(self):

        print('test2 is in progressing...')

        c=Count(10,20)

        self.assertEqual(c.add(),30)

 

    def tearDown(self) -> None:

        print('test end...')

 

 

if __name__=='__main__':

    # unittest.main()

    #调用unittest的TestSuite类来创建测试套件(根据TestSuite类生成一个对象)

    suite=unittest.TestSuite()

    #使用测试套件提供的addTest方法将测试用例加载进测试套件

    suite.addTest(TestCount("test_add2"))

    suite.addTest(TestCount("test_add1"))

    #使用测试运行器执行测试套件(根据TestRunner类生成一个对象,调用对象的run方法执行测试套件)

    runner=unittest.TextTestRunner()

    runner.run(suite)

 

注解:

  • TestSuite类:组装测试用例,传递给test runner进行测试执行
  • TextTestRunner类:测试用例执行类,text表示以文本的形式输出结果

 

3)         Unittest常用的断言方法

断言:将预期结果和实际结果进行比较的过程

断言方法的作用:将预期结果和实际结果做比较

 

Unittest提供了丰富的断言方法:

 

  • assertEqual(a,b):判断a和b是否相等,相等则测试通过,不相等则测试失败
  • assertNotEqual(a,b):判断a和b是否不相等,相等则测试失败,不相等则测试通过
  • assertTrue(x):判断表达式x是否为True(成立),成立则测试通过,不成立则测试失败
  • assertFalse(x):
  • assertIs(a,b):判断a,b是否为同一个对象,是则测试通过,不是则测试失败
  • assertIsNot(a,b):
  • assertIsNone(x):判断x是否为None,不是则测试失败
  • assertIsNotNone(x)
  • assertIn(a,b):判断a是否在b中,不在则测试失败
  • assertNotIn(a,b):
  • assertIsInstance(a,b):判断a是否是b的实例,不是则测试失败
  • assertNotIsInstance(a,b):

 

4)         跳过测试和预期失败

在运行测试时,有时需要跳过某些测试用例或者将某些测试用例标记为预期失败,unittest提供了实现这些需求的装饰器。

装饰器:一个python函数,它可以让它所修饰的函数在不做任何修改的前提下增加额外的功能

 

  • @unittest.skip(原因):无条件跳过该测试用例,可以说明下跳过测试的原因
  • @unittest.skipIf(条件,原因):如果条件成立,跳过该测试用例
  • @unittest.skipUnless(条件,原因):如果条件成立,则执行该测试用例
  • @unittest.expectedFailure:如果某条测试用例使用该装饰器,如果测试失败,它会被标记为预期成功,如果测试通过了,它会被标记为预期失败。

 

import unittest

 

class MyTest(unittest.TestCase):

 

    @unittest.skip('无条件跳过该测试')

    def test_skip(self):

        print('print a')

 

    @unittest.skipIf(2>1,'当条件成立,跳过该测试')

    def test_skipif(self):

        print('print b')

 

    @unittest.skipUnless(2>1,'当条件成立,执行该测试')

    def test_skipunless(self):

        print('print c')

 

    @unittest.expectedFailure

    def test_expectedfailure(self):

        self.assertEqual(2,3)

 

if __name__=='__main__':

    unittest.main()

 

断言方法的举例:

 

assertEqual(a,b)

assertIn()

assertTrue()

 

示例:

 

本次课程目标:

  1. 单元测试用例的组织与执行
  2. 使用discover()方法自动发现测试用例
  3. 测试用例的执行顺序
  4. 使用unittest组织自动化测试脚本

 

 

  1. 单元测试用例的组织与执行

import unittest

from calculator import Count

 

class TestAdd(unittest.TestCase):

 

    def setUp(self) -> None:

        print('test start...')

 

    def test_add1(self):

        print('test_add1 is in progressing...')

        c=Count(1,2)

        self.assertEqual(c.add(),3)

 

    def test_add2(self):

        print('test_add2 is in progressing...')

        c=Count(10,20)

        self.assertEqual(c.add(),30)

 

    def tearDown(self) -> None:

        print('test end...')

 

class TestSub(unittest.TestCase):

 

    def setUp(self) -> None:

        print('test start...')

 

    def test_sub1(self):

        print('test_sub1 is in progressing...')

        c=Count(1,2)

        self.assertEqual(c.sub(),-1)

 

    def test_sub2(self):

        print('test_sub2 is in progressing...')

        c=Count(10,20)

        self.assertEqual(c.sub(),-10)

 

    def tearDown(self) -> None:

        print('test end...')

 

if __name__ == '__main__':

    # unittest.main()

    #构造测试套件

    #调用unittest提供的TestSuite()类创建测试套件

    suite=unittest.TestSuite()

    #使用测试套件提供的addTest()方法加载测试用例到测试套件

    suite.addTest(TestAdd("test_add1"))

    suite.addTest(TestSub("test_sub1"))

    suite.addTest(TestAdd("test_add2"))

    suite.addTest(TestSub("test_sub2"))

    #执行测试

    runner=unittest.TextTestRunner()

    runner.run(suite)

   

注意:以上代码可以优化,如果每个类中的setUp()和tearDown()所作的事情都一样,

那么,我们可以将它们封装到一个类里,其他类继承它,就不用重复去书写。

 

import unittest

from calculator import Count

 

class MyTest(unittest.TestCase):

 

    def setUp(self) -> None:

        print('test start...')

 

    def tearDown(self) -> None:

        print('test end...')

 

class TestAdd(MyTest):

 

    def test_add1(self):

        print('test_add1 is in progressing...')

        c=Count(1,2)

        self.assertEqual(c.add(),3)

 

    def test_add2(self):

        print('test_add2 is in progressing...')

        c=Count(10,20)

        self.assertEqual(c.add(),30)

 

class TestSub(MyTest):

 

    def test_sub1(self):

        print('test_sub1 is in progressing...')

        c=Count(1,2)

        self.assertEqual(c.sub(),-1)

 

    def test_sub2(self):

        print('test_sub2 is in progressing...')

        c=Count(10,20)

        self.assertEqual(c.sub(),-10)

 

 

if __name__ == '__main__':

    # unittest.main()

    #构造测试套件

    #调用unittest提供的TestSuite()类创建测试套件

    suite=unittest.TestSuite()

    #使用测试套件提供的addTest()方法加载测试用例到测试套件

    suite.addTest(TestAdd("test_add1"))

    suite.addTest(TestSub("test_sub1"))

    suite.addTest(TestAdd("test_add2"))

    suite.addTest(TestSub("test_sub2"))

    #执行测试

    runner=unittest.TextTestRunner()

    runner.run(suite)

 

         随着软件功能的不断增加,对应的测试用例也会增加,如果你把所有的测试用例都写在一个py文件里,那么这个文件就会变得非常大,代码的可读性和可维护性就会变得很差。在实际工作中,通常我们会将测试用例按照所测试的功能进行拆分,分散到不同的文件里。

 

上述代码可以拆分为5个文件:

calculator.py  要测试的功能

testadd.py      整数加法功能的测试用例

testsub.py       整数减法功能的测试用例

mytest.py         所有测试用例公用的方法

runtest.py       测试用例的执行

 

代码见chaifen文件夹

 

问题:以上拆分设计没有解决添加用例的问题,当用例非常多的时候,通过addTest()添加用例非常麻烦,这个时候,我们可以选择使用unittest提供的discover()方法自动识别测试用例。

 

  1. 使用discover自动发现测试用例

import unittest

 

 

if __name__ == '__main__':

    discover=unittest.defaultTestLoader.discover('./',pattern="test*.py")

    runner=unittest.TextTestRunner()

runner.run(discover)

 

 

注解:

ü  unittest里的defaultTestLoader下提供了discover()方法,可以自动去发现某个目录下的测试用例并加载进来

ü  discover()方法:第一个参数指明测试用例所在目录,第二个参数指明测试用例文件名的匹配模式

 

  1. 测试用例的执行顺序

默认的加载顺序:unittest默认根据ASCII码(为了在计算机中区分字符给的一种编码)的顺序来加载测试用例。数字与字母的顺序为:0-9,A-Z,a-z。

所以,Add类优先于Sub类,test_add1优先于test_add2

 

import unittest

 

class B(unittest.TestCase):

 

    def test_c(self):

        print('test c')

 

    def test_a(self):

        print('test a')

 

class A(unittest.TestCase):

 

    def test_b(self):

        print('test b')

 

 

if __name__ == '__main__':

unittest.main()

 

         注解:

ü  如果你希望按照特定的顺序来执行测试用例,那么有两种方法:

n  给测试类和测试方法命令的时候按照ASCII码的顺序去组织

n  使用测试套件提供的addtest()方法加载,会按照测试用例加载的先后顺序去执行

 

小结:

我们通过unittest的学习,目的并不是为了编写单元测试用例,而是为了使用它来组织我们的web自动化测试用例。利用单元测试框架提供的测试用例编写、组织、断言、执行以及结果报告生成,可以很好的辅助我们进行web自动化测试的开发。

 

  1. 使用unittest组织自动化测试脚本

见test_web文件夹

 

回顾:

  1. unittest:Python自带的一个单元测试框架

实现方式:通过编写的测试类继承unittest.TestCase类,就能自动执行测试类中的特定方法:

  • test打头的方法:测试方法,会自动执行
  • setUp()方法:是每个测试方法执行前都会执行的方法,做测试前的初始化工作
  • tearDown()方法:是每个测试方法执行后都会执行的方法,做测试后的清理工作

 

注意:测试类中的其他方法不会自动执行(a,b…)

 

  1. 单元测试的加载方式:
  • unittest.main()
  • 将测试用例添加到测试套件,然后使用测试运行器执行

discover()

  1. unittest里常用的断言方法:self.assertXXX系列的方法来做预期结果和实际结果的比较。

 

 

 

元素定位:

 

Web UI自动化测试要做的事情就是模拟鼠标和键盘操作页面元素。所以,自动化测试要做的事情(实施过程)包含两个部分:

  • 元素定位:定位到网页上的页面元素,并获取该页面元素对象
  • 操作元素:操作该页面的元素,例如:输入、点击等

 

元素定位以及对元素的操作可以通过WebDriver API来实现。

WebDriver API属于Selenium体系设计出来的用于操作浏览器的一套API。

站在WebDriver的角度,它针对多种编程语言都实现了一遍这一套API,所以它支持多种编程语言;

站在编程语言(Python)的角度,WebDriver是Python用于实现Web自动化的第三方库。

 

API:简单来理解,就是预先定义好的一些类、方法、属性等等,它们可供我们直接调用,用以实现特定目的(WebDriver API实现了对Web页面元素的定位与操作)

 

  1. 在WebDriver API里,有一个WebElement类,它里面定义好了元素定位方法。元素定位方法可分为两个系列:

 

1)         find_element系列:用于定位单个的页面元素。一共提供了8种元素定位方法:

find_element_by_id(‘xx’)

find_element_by_name(‘xx’)

find_element_by_class_name(‘xx’)

find_element_by_tag_name(‘xx’)

find_element_by_link_text(‘xx’)

find_element_by_partial_link_text(‘xx’)

find_element_by_xpath(‘xx’)

find_element_by_css_selector(‘xx’)

 

2)         find_elements系列:用于定位一组页面元素,以列表的方式返回。

 

 

  1. 元素定位的基础知识

 

网页文本的结构的特点:

 

1)         由标签对所组成

2)         标签可以有各种属性

3)         标签对之间可以有文本数据

4)         标签之间有层级关系

 

理解以上的这些特性有助于你学习元素定位方法。

 

  1. 8大定位方式。

 

1)         id定位:通过元素的id属性取值来定位元素。

 

注意:在自动化测试实施过程中,可能会出现页面元素无id属性值,就没法使用id定位,可以前期跟开发人员沟通,去给相关页面元素设置id值,以提高网页程序的可测试性,降低自动化测试的实施难度,提升效率。

 

2)         name定位:通过元素的name属性来定位元素。

3)         class定位:通过元素的class属性来定位元素。

4)         tag name定位:通过元素的标签名来定位元素

5)         link text定位:通过链接文本信息来定位元素

6)         partial link text定位:是对link text的补充,有些文本链接比较长,或者有些文本链接其中一部分是动态生成的,这个时候,我们可以选择取该文本链接的一部分进行定位,只要保证这部分信息可以唯一的标识这个链接。

7)         Xpath定位

Xpath是一种在xml文档中定位元素的语言。Web开发的HTML跟XML很相似,所以Xpath也可用于Web中做元素定位。

(1)       使用绝对路径的方式来定位

绝对路径定位方式指的是从网页的HTML代码结构中,从最外层一层层的写到需要被定位的页面元素。绝对路径起始于斜杠/,每一步都被斜杠分割。

 

Eg:/html/body/div[2]/form/input[3]

 

注解:

  • 第一个/表示根目录
  • 使用中括号可以选择分支,div[2]代表的是当前层级下的第二个div标签
  • 一般情况下比较少的使用绝对路径方式做定位,原因在于绝对路径的表达式通常太长不便于代码维护,代码的微小改变都可能导致该路径失效,从而无法完成元素的定位。

(2)       使用相对路径的方式定位

不是从根目录写起,相对路径起始于双斜杠//

 

Eg://input[@id=’kw’]

 

注解:

  • 示例的含义:在当前页面找到任意目录下的input元素且该元素的id属性取值为kw
  • //表示的是任意目录下
  • 属性以@开头
  • 所选取的属性可以是任意属性,只要它有利于标识这个元素即可
  • 相对路径的xpath表达式更简洁,推荐使用相对路径的xpath表达式,可大大降低测试脚本中定位表达式的维护成本

 

(3)       层级和属性结合来定位(使用得最多)

 

Eg://span[@class=’tgs’]/input

 

注解:

  • 示例的含义:任意目录下的span标签,该标签的class属性取值为tgs,我们找到这个标签下的input标签所对应的元素。
  • 有时候,一个元素本身没有可以唯一标识这个元素的属性值,那么我们可以找其上一层,甚至上上一层元素
  • 可以选择使用谷歌/火狐浏览器的开发者工具:F12——》使用元素拾取器在想定位的页面元素上点一下,代码区域就会高亮显示该元素所对应的代码,你在代码上右击,选择复制——》复制了xpath——》到需要使用xpath表达式的地方粘贴就能看到这个xpath表达式
  • 有时候,可能会出现一个属性不能唯一的标识某个元素,可以使用逻辑运算符and连接多个属性来进行标识:

<input class=’su’ name=’ie1’ />

<input class=’aa’ name=’ie1’ />

<input class=’su’ name=’ie3’ />

假如想唯一的定位到第一个元素,那么xpath表达式可以写成:

//input[@class=’su’ and @name=’ie1’]

8)         CSS定位

CSS:一种用于描述网页样式的语言

CSS格式:选择器+样式声明语句(一组或多组属性值所组成)

 

选择器{属性1:值1;属性2:值2;……属性n:值n}

注解:选择器指明了后面{}里的样式作用于页面中的哪些元素;样式声明语句决定了样式的具体表现。

 

CSS常见的选择器:

  • 类选择器:.class             eg:   .btn           选择class=’btn’的所有元素
  • Id选择器:#id                  eg:  #btn         选择id=’btn’的所有元素
  • 元素选择器:使用的是元素名称         eg:  p 选择所有标签名称为p的元素
  • 属性选择器:[属性=值]        eg:[title=’btn’] 选择title=’btn’的所有元素

 

选择所有的元素:*

 

在CSS里表示层级关系,使用的是>:

Eg: div#div1>input#input1

该CSS表达式的含义是:选择父元素为div(id取值为div1)下的下一个层级的input元素(id取值为input1)

 

表示同一级相邻,使用+:

Eg:div#div1>input+a

该CSS表达式的含义是:选择父元素为div(id取值为div1)下的下一个层级的input元素后面的同级且临近的链接元素a

 

更多的CSS表达式的示例:

find_element_by_css_selector(‘.btn’)

find_element_by_css_selector(‘#btn’)

find_element_by_css_selector(‘[title=”btn”]’)

find_element_by_css_selector(“[title=’btn‘]“)

find_element_by_css_selector(‘[title=btn]’)

find_element_by_css_selector(”[title=btn]”)

 

注意:对于CSS的属性值来讲,可加引号,也可以不加,但注意要和整个字符串的引号进行区分。

 

(1)       使用绝对路径定位:

html>body>div>input[value=x]

(2)       使用相对路径定位:

input[value=x]

(3)       使用id,class,其他属性定位:

input#x

input.y

input[type=’checkbox’]

posted @ 2019-12-22 13:19  青弈龙  阅读(772)  评论(0)    收藏  举报