2017-07-26 53 views
1

什么是Pythonic方式做一个函数的正确的单元测试,取决于pyodbc所做的SQL查询?据我所知,最好的方法是模拟从SQL服务器返回输出的函数。问题是模拟应该返回什么?Pythonic方式来模拟pyodbc.Row

我的设置: 在LIB1:

def selectSQL(connection, query): 
    cursor = connection.cursor() 
    cursor.execute(query) 
    return cursor.fetchall() 

在LIB2:

def function_to_be_tested(cxnx): 
    my_query = "SELECT r1, r2 FROM t1" 
    rows = lib1.selectSQL(cxnx, my_query) 
    # do someting with the rows like: 
    a = 0 
    for row in rows 
     a += row.r1 * row.r2 
    return a 

我有以下sollution传来:

  • 打印lib1.selectSQL(cxnx, my_query)到文件
  • 从lib1.sel插入数据ectSQL到namedtuple

out_tuple = namedtuple('out1', ["r1", "r2"]) 
printed_data = [(1,2),(2,3)] 
out = [out_tuple(*row) for row in printed_data] 

def test_mockSelectSQL(self): 
    piotrSQL.selectSQL = MagicMock() 
    piotrSQL.selectSQL.side_effect = [out] 
    self.assertEqual(lib2.function_to_be_tested(True), 7) 

我唯一担心的是,模拟返回namedtuple不是pyodbc.Row像原来的功能。我已经检查继上搜索如何正确地创建pyodbc.Row信息网站:

在单元测试pyodbc的是没有的,如果构造 - 既没有我在源代码中找到它(但是我是新手,所以我可能省略了它)...但是我已经在Row文档中找到以下信息:

Howeve r,有一些pyodbc添加,使它们非常方便:

  • 值可以通过列名访问。

  • 即使在光标关闭后,也可以访问Cursor.description值。

  • 值可以被替换。

  • 来自同一select语句的行共享内存。

所以接缝的namedtuple其实是在相同的方式,pyodbc.Row行为(当谈到访问值)。 pyodbc.Row是否有单独的Python测试方法?我们可以假设这是一个很好的模拟吗?

+1

我会创建一个内存[sqlite](https://docs.python.org/2/library/sqlite3.html)表与模拟数据和钩入。 fromt他DOC我联系:'你也可以提供专门的名字:内存:创造RAM.' – Nullman

+0

数据库@Nullman 这没有按pyodbc我可以通过访问该行中的值: row.value1 和在sqlite中,我必须使用: row ['value1'] 因此,如果我将pyodbc连接替换为sqlite连接,代码将失败。其他问题是,sqlite不支持在其他地方打破我的测试的日期时间对象... –

+0

你正在使用哪种sql数据库? – Nullman

回答

1

而且从@Nullman到问题的意见建议,如果你想使用一个内存数据库,你可以尝试使用SQLite的ODBC驱动程序,所以你可以回到像这样实际pyodbc.Row对象:

import pyodbc 
conn_str = 'Driver=SQLite3 ODBC Driver;Database=:memory:' 
cnxn = pyodbc.connect(conn_str, autocommit=True) 
crsr = cnxn.cursor() 

# create test data 
crsr.execute("CREATE TABLE table1 (id INTEGER PRIMARY KEY, dtm DATETIME)") 
crsr.execute("INSERT INTO table1 (dtm) VALUES ('2017-07-26 08:08:08')") 

# test retrieval 
crsr.execute("SELECT * FROM table1") 
print(crsr.fetchall()) 
# prints: 
# [(1, datetime.datetime(2017, 7, 26, 8, 8, 8))] 

crsr.close() 
cnxn.close() 

我刚刚测试过它,它在Windows上的PyCharm中为我工作。

+1

我没有在这里访问odbc所以我不能测试它,很好的工作验证! – Nullman