数据驱动测试是自动化测试领域比较主流的设计模式之一,也是高级自动化测试工程师必备的技能之一。数据驱动框架是一种自动化测试框架,其目的在于可以让相同的脚本使用不同的测试数据,测试数据和测试行为(脚本)完全分离,便于测试的维护和扩展。
例如,测试登录操作时,需要用到多种用户来登录,然后验证系统的响应是否正确。这里,我们就可以先准备好要登录的用户数据(比如用户名和密码),只需一个自动化登录脚本即可实现。
数据驱动测试的一般步骤如下:
(1)编写脚本,脚本需要有可扩展性并且支持从对象、文件或者持久化数据库中读取测试数据。
(2)准备测试数据到文件或者数据库等外部介质中。
(3)循环调用介质中的数据库来驱动脚本执行。
(4)验证自动化测试结果。
在数据驱动框架中需要掌握 Python 对文件的基本操作等,在这一章中将详细讲解有关文件的相关操作。
之前的章节,我们都是将测试数据写在代码中,这种在程序中直接给代码赋值的形式俗称「hardcode」。直接将数据写在源代码中,若测试数据有变,并不利于数据的修改和维护,会造成程序的质量变低。
我们可以尝试通过将测试数据放到 Excel 文档中来实现测试数据的管理,而数据驱动框架的概念正是由此而来。
创建 Excel 文件「testdata.xlsx」以备测试之用,具体数据如图 10.29 所示。
图 10.29
下一步需要用 Python 实现读取 Excel 文件的函数功能以备测试之用。代码如下:
上述代码创建了命名为 read_excel 的函数,并设置了三个参数。其中,filename 是 Excel 文件名,可以指定为相对路径;Index 是 Sheet 的编号,比如 Excel 中 Sheet1 表格的 index 值为 0;column 是表格的列,比如 A 列对应的值为 0。
以上是用列表的方式来存储 Excel 中读取的数据,通过观察可以看到 A 列有 3 行数据,B 列有 4 行数据。其实这种情况下用字典的形式来存储数据比较好,每一列数据存储到一个列表中。新的读取 Excel 文件的函数代码如下:
以下代码调用为输出所有的 excel 文件中第一个 sheet 的所有数据,代码执行结果如图 10.30 所示,和 Excel 文件中的数据是一致的。从输出结果可以看到 Excel 文件有 3 行 2 列,还有数据的实际情况。
图 10.30
关于日志,笔者相信软件开发人员或者测试人员对于这个概念应该不会陌生。它是可以追踪应用运行时所发生的事件的一种方法。事件(Event)是有轻重缓急的,可以用严重等级来区分,相应的日志也有日志等级之分。
日志非常重要,通过日志可以方便用户了解应用的运行情况,如果日志内容或者程度足够丰富,也可以分析诸如用户偏好、习惯、操作行为等信息,也是现在流行的大数据分析的一种。所以说,日志非常重要。一般来说,日志的作用有以下两点:
(1)程序调试。
(2)了解软件健康状况,查看软件运行是否正常等。现在基于日志的分析统计软件也有很多,比如 Splunk 就是其中的佼佼者,它提供了很多日志分析、查询、统计功能,还有强大的报表定制化功能。
不同系统或者软件有不同的日志等级的定义,总结一下,常用的日志等级如下:
· DEBUG
· INFO
· WARNING
· ERROR
· ALERT
· NOTICE
· CRITICAL
日志的一般组成结构如下:
· 事件发生的时间,有些国际化软件还要有时区的信息,比如 GMT 等。
· 事件的发生位置,比如事件发生时,程序执行的代码信息等。
· 事件的严重程度,也就是日志等级。
· 事件的内容,一般由开发者控制,哪些内容要输出,以及以什么样的格式输出。
一般的开发语言都会有日志相关的模块(功能),比如 log4j、log4php 等功能强大,使用简单。Python 自身也提供了日志的标准库模块 logging。
logging 模块的日志级别设定有:
· DEBUG,通常打印的日志信息很详细,这种级别的设定场景一般是在进行问题定位和调试。
· INFO,信息详细程度仅次于 DEBUG,通常只记录关键的信息点,用于确认软件是否按照正常的预期在运行。
· WARNING,当某些异常信息发生时系统记录的日志信息,而此时软件一般是正常运行的。比如 App 服务器内存(Memory)抵达使用的临界点,比较成熟的软件会有日志提醒。
· ERROR,由于一个更加严重的问题导致软件运行不正常而记录的相关信息。比如内容溢出异常等。
· CRITICAL,当严重的错误发生时直接导致宕机、软件服务等无法使用,或者在访问时记录相关的信息。
日志的等级从低到高依次为 DEBUG < INFO < WARNING < ERROR < CRITICAL,但是相应的日志记录的信息量是逐步减少的。
logging 模块定义日志级别常用的函数:
· logging.debug(msg,*args,**kwargs)
· logging.info(msg,*args,**kwargs)
· logging.warning (msg,*args,**kwargs)
· logging.error(msg,*args,**kwargs)
· logging.critical(msg,*args,**kwargs)
以上函数的作用是为了创建如 DEBUG、INFO、WARNING、ERROR、CRITICAL 等日志级别的日志。此外,还有两种常用的函数,作用如下:
· logging.log(level,*args,**kwargs):用于创建一个日志级别为 level 的日志记录。
· logging.basicConfig(**kwargs):对 root logger 进行配置,主要用于指定「日志级别」「日志格式」「日志输出位置/文件」「日志文件的打开模式」等信息。
logging 模块的四大组件如下:
(1)loggers(提供应用程序码直接使用的接口)。
(2)handlers(用于将日志记录发送到指定的位置)。
(3)filters(提供日志过滤功能)。
(4)formatters(提供日志输出格式设定功能)。
以下为简单的 logging 模块使用案例:
以上案例也可以使用另外一种写法,源码如下:
在控制台中输出结果如下:
我们会发现,DEBUG 和 NFO 级别的日志没有输出来。这是因为 logging 模块提供的日志记录函数所使用的日志器设置的级别为 WARNING,因此只有 WARNING 级别及大于该级别的(如 ERROR、CRITICAL)日志才会输出,而严重级别比 WARNNING 低的日志被丢弃了。
打印出来的日志信息如「WARNING:root:I am a warning level log.」各个字段的含义分别是日志级别、日志器名称和日志内容。日志之所以用这样的格式输出,是因为日志器中设置的是默认格式 BASIC_FORMAT,其值为「%(levelname)s:%(name)s:%(message)s」。
另外,为什么日志输出到控制台而没有输出到别的地方?原因是日志器中用的是默认输出位置「sys.stderr」。
如果要改变日志输出位置,需要手动调用函数 basicConfig()进行设置。basicConfig()函数的定义为「logging.basicConfig(**kwargs)」。
该函数的参数描述如下:
· Filename:指定输出目标文件名,用于保存日志信息。设置该配置项后,日志就不会输出到控制台了。
· FileMode:指定日志文件的打开模式,默认为「a」,且仅在 filename 指定时生效。
· Format:指定输出的格式和内容,format 可以输出很多有用的信息。
· DateFmt:指定日期/时间格式。
· Level:指定日志器的日志级别。
· Stream:指定日志输出目标 stream,比如「sys.stdout」「sys.stderr」。需要注意的是,stream 配置项和 filename 配置项不能同时提供,可能会造成冲突和产生 ValueError 异常。
· Style:Python3 之后新添加的配置项,用于指定 format 格式字符串的风格,可取值为「%」「{」和「$」。其默认值为「%」。
Handlers:Python 6.3 之后新添加的配置项。该选项如果被指定,它应该是一个创建了多个 Handler 的可迭代对象,这些 handler 将会被添加到 root logger。需要说明的是,filename、stream 和 handlers 这三个配置项只能有一个存在,不能同时出现 2 个或 3 个,否则会引发 ValueError 异常。
logging 模块关于日志格式字符串字段的介绍如表 10.3 所示。
表 10.3
配置日志器的日志级别,代码如下:
控制台输出的内容如下:
以上所有等级的日志信息都被输出了,说明之前的配置已经生效。在配置了日志级别的基础上,再配置日志输出、日志文件和日志格式,代码如下:
代码执行完毕,在当前目录下生成一个日志文件「log1.log」,内容如下:
在以上配置的基础上,我们也可以加上日期/时间格式的配置,测试源码如下:
代码执行完毕,在当前目录下生成一个日志文件「log6.log」,内容如下:
以上是对 Python Log 的一个简单的介绍,如果想对 Python Log 有更深入的了解,请参考官方文档「https://docs.python.org/6.7/howto/logging.html」。
下面定义一个 log 函数,目的是定义 logging 的 basicConfig 等信息。其中有一个比较重要的信息是,Log 存放的文件在当前目录下的 log-selenium.log 文件中,具体代码如下: