我应该如何重写我的数据库执行/提交以使其适合单元测试?

jus*_*tin 6 python database unit-testing

我一直在努力开始进行单元测试,同时开发一个小的cli程序.

我的程序基本上解析命令行参数和选项,并决定调用哪个函数.每个函数都对数据库执行一些操作.

所以,例如,我可能有一个创建函数:

def create(self, opts, args):
    #I've left out the error handling.
    strtime = datetime.datetime.now().strftime("%D %H:%M")
    vals = (strtime, opts.message, opts.keywords, False)
    self.execute("insert into mytable values (?, ?, ?, ?)", vals)
    self.commit()
Run Code Online (Sandbox Code Playgroud)

我的测试用例应该调用这个函数,然后执行select sql来检查是否输入了行?这听起来很合理,但也使测试更难维护.你会重写函数来返回一些东西并检查返回值吗?

谢谢

Ned*_*der 8

Alex的答案涵盖了依赖注入方法.另一个是考虑你的方法.目前,它有两个阶段:构造SQL语句,并执行SQL语句.您不想测试第二阶段:您没有编写SQL引擎或数据库,您可以假设它们正常工作.阶段1是您的工作:构建SQL语句.因此,您可以重新组织代码,以便只测试阶段1:

def create_sql(self, opts, args):
    #I've left out the error handling.
    strtime = datetime.datetime.now().strftime("%D %H:%M")
    vals = (strtime, opts.message, opts.keywords, False)
    return "insert into mytable values (?, ?, ?, ?)", vals

def create(self, opts, args):
    self.execute(*self.create_sql(opts, args))
    self.commit()
Run Code Online (Sandbox Code Playgroud)

create_sql函数是阶段1,现在它以一种允许您直接针对它编写测试的方式表达:它接受值并返回值,因此您可以编写涵盖其功能的单元测试.该create函数本身现在是简单,不用那么全面测试:你能有几个测试,证明它确实执行SQL正确,但你不必支付在所有的特殊情况create.

BTW:来自Pycon(测试和可测试性)的视频可能很有趣.


Ale*_*lli 6

我肯定会重构这个方法以便于测试 - 例如,依赖注入可能会有所帮助:

def create(self, opts, args, strtime=None, exec_and_commit=None):
    #I've left out the error handling.
    if strtime is None:
        strtime = datetime.datetime.now().strftime("%D %H:%M")
    vals = (strtime, opts.message, opts.keywords, False)
    if exec_and_commit is None:
        exec_and_commit = self.execute_and_commit
    exec_and_commit("insert into mytable values (?, ?, ?, ?)", vals)
Run Code Online (Sandbox Code Playgroud)

这当然假设你有一个execute_and_commit调用方法execute然后调用commit方法.

这样,测试代码可以strtime为其注入一个已知值,并注入自己的callable,exec_and_commit以验证它是否被预期的参数调用.