Python Behave 框架写的自动化测试,有必要上 ORM 吗?

如题,最近在看 PonyORM,感觉测试的代码中加入 ORM 有很多不方便的地方啊,也可能是不会用,求教
Python Behave 框架写的自动化测试,有必要上 ORM 吗?

4 回复

ORM 最大的好处是:摆脱了裸写 SQL 造成的对特定数据库方言的依赖,便于在不同数据库之间迁移或部署。
只有一两个表的情况用 ORM 没有太大意义体现不出来什么优势。大量的表和关系要管理时候用起来才值得。还有就是多人合作的项目中便于统一接口集中控制。
目前建议你用 sqlalchemy,这种冷门的 ORM 最好别学,大概率耽误功夫。


这问题挺实际的。我的看法是:通常没必要,但特定场景下可以考虑。

Behave做的是BDD验收测试,重点是验证业务行为,不是数据操作。大部分情况下,直接用数据库驱动(如psycopg2、pymysql)或者测试框架的数据夹具更直接。

什么时候可能需要ORM:

  1. 你的测试需要操作复杂的对象关系,手动拼SQL太麻烦
  2. 测试逻辑和产品代码共享同一个数据模型层
  3. 需要测试ORM层本身的逻辑

示例对比:

# 直接使用数据库驱动(推荐大多数情况)
import psycopg2

def insert_user_direct(db_config, name, email):
    """直接SQL插入"""
    conn = psycopd2.connect(**db_config)
    cursor = conn.cursor()
    cursor.execute(
        "INSERT INTO users (name, email) VALUES (%s, %s) RETURNING id",
        (name, email)
    )
    user_id = cursor.fetchone()[0]
    conn.commit()
    cursor.close()
    conn.close()
    return user_id

# 使用ORM(如SQLAlchemy)
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    email = Column(String)

def insert_user_orm(db_url, name, email):
    """通过ORM插入"""
    engine = create_engine(db_url)
    Session = sessionmaker(bind=engine)
    session = Session()
    
    user = User(name=name, email=email)
    session.add(user)
    session.commit()
    user_id = user.id
    session.close()
    return user_id

直接SQL的优点:

  • 测试更接近真实查询
  • 没有ORM的抽象开销
  • 更容易控制数据库状态
  • 依赖更少,运行更快

ORM的优点:

  • 对象操作更符合业务思维
  • 复用产品代码的模型定义
  • 避免SQL语法错误

建议: 除非测试ORM本身,否则优先用直接数据库操作。

sqlalchemy 听说非常难用,PonyORM peewee 稍微简单点

要说 python 的 ORM 库里面 sqlacchemy 基本上是事实标准,你要是用的生产环境以后也有很多需求,非它莫数, 能很好地支持事务和分表就这两项其它的 ORM 就没的比。Pony 和 peewee 之类的只是小玩具。而且 sqlalchemy 在其它好几语言都有实现比如 golang 之类的。
另一个好用的 ORM 就算是 Django 内置带的那个了,其实是从 RoR 那里克隆来的用的 Active Record 方式,上手容易文档丰富,用起来比较直观,不象 sqlachemy 那么拧巴。因为 sqlachemy 用的 data mapper 实现,必须使用另外的持久层来保持与数据库的交互,好处是代码和数据库也是完全隔离的。

回到顶部