2017-07-26 87 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