sqlalchemy是python当中比较出名的orm(object relational mapping)程序, 即对象映射关系程序。
之所以选择sqlalchemy,是因为相较于其他python库,如storm、sqlobject等,其提供了企业级API,使得代码有健壮性和适应性,其设计灵活,使得能轻松写复杂查询,同时提供了兼容众多数据库(如 SQLite、MySQL、Postgres、Oracle、MS-SQL、SQLServer 和 Firebird)的持久性模型。
首先,介绍一下sqlalchemy 的架构和工作原理:
如图所示,sqlalchemy主要分为三个模块:
ORM:实现一个Mapper对象,将Python中定义的类与数据库中的表建立关联,以及类的实例(instance)和表的行(row)建立关联;
Core:Core部分与ORM解耦和,如果想通过session管理、连接池管理、数据库语句执行sql语句,就可使用core。Core中包含的部件可以直接支持使用SQL Expression和RAW SQL。使用SQL Expression阅读性和可维护程度高,而RAW SQL更灵活,支持复杂的SQL语句;
DBAPI:sqlalchemy 没有提供直接连接数据库的功能,因此第三方库提供来实现数据库的连接。
通过对图的分析,我们可以清晰得出:使用sqlalchemy可以分为三种方式:
使用sql expression,通过 SQLAlchemy 的方法写sql表达式,简介的写sql;
使用raw sql,直接书写 sql;
使用ORM避开直接书写 sql;
简单了解sqlalchemy后,接下来介绍的主要是我们自动化框架中如何运用sqlalchemy的ORM方式操作数据库,提供统一的数据库验证方法协助完成自动化单元测试中的验证工作。
首先来一张自动化框架数据库连接的整体思维图:
框架中对数据库的操作大致分为五个部分:
database_factory模块:定义engine和操作数据库的一些公共方法;
connect_to_database装饰器:通过对database_operator模块中方法装饰(主要获取数据库表的映射类),完成数据库engine和session的创建,支持多个数据库session的建立,同时支持使用sqlalchemy的三种方式;
database_operator模块:通过调用database_factory模块公共方法来定义一些具体的操作表的语句;
database_object模块:自定义类;
database_assertion模块:对外提供公共的查询数据库方法,校验数据库值方法等。
思维图中简要展示了各个模块之间的联系,接下来详细介绍各个模块之间如何协同工作,完成对数据库的操作。
database_factory模块
build_engine方法定义,供connect_to_database装饰器调用;
查询数据库方法get_record_from_table等(其他方法此处忽略,重点讲解查询方法,单元测试中数据库校验只用到查询方法),供database_operator模块调用;
示例代码如下:
connect_to_database装饰器
支持ORM模式和RAW SQL模式;
支持同时连接多个数据库session;
数据库连接sql操作完成关闭所有的session;
示例代码如下:
database_operator模块
定义了具体的操作表的方法,被connect_to_database装饰,调用database_factory中公共方法;
示例代码如下:
database_object模块
定义所有的数据库表映射类,供database_operator模块连接数据库表使用;
python库sqlacodegen可以自动生成models文件,我们的自动化框架中支持oracle和mysql数据库,使用sqlacodegen产生这两种数据库映射类的语法如下:
1. oracle:
2. mysql:
生成的映射类示例代码如下:
所有的映射类都是继承自基类Base,declarative_base() 创建了一个BaseModel 类,这个类的子类可以自动与一个表关联。此处以 WfRoleResPerm 类为例,它的 __tablename__ 属性就是数据库中该表的名称,它有 role_id 和 perm_id 这两个字段,分别为Numeric和 38 个定长字符。
database_assertion模块
get_column_value_from_table方法底层调用database_operator模块中的具体连接数据库方法;
提供公共的校验数据模块,校验数据是否正确或者是否为空,主要方便单元测试中对数据update的校验;
示例代码如下:
编写公共的数据库校验方法,首先用户不需要知道底层数据库连接、查询等是如何实现的,同时对外(即单元测试)提供了统一查询数据库方法,不至于每个单元测试中调用方法各异,最后其支持轮询查询数据库表,使得没必要每次都分开去查询不同的数据库表。
了解了这几部分模块工作原理后,我们来看看单元测试用例中是如何运用的。
可以看到,只需要定义查询的json数据,调用公共的查询方法就ok啦。
本文作者:黄媛(点融黑帮),目前就职于点融网Techops QA团队,测试开发工程师,专注于自动化测试。