0

私は実際のデータベースに接続するためにpymysqlクライアントライブラリを使用しています。私はpymysqlを使用してデータベースに接続し、データベースのみの操作を行うモジュール内の関数を持っています。実際のデータベースにヒットせずにPythonでこの関数をユニットテストする方法は?Python Unit Test:データベース操作を含むモジュールを単体テストする方法は?

import pymysql 

def connectDB(self): 

# Connect to the database 
connection = pymysql.connect(host='localhost', 
          user='user', 
          password='passwd', 
          db='db') 

try: 
    with connection.cursor() as cursor: 
     # Create a new record 
     sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)" 
     cursor.execute(sql, ('[email protected]', 'newpassword')) 


    connection.commit() 
+1

データベースをモックするオプション 'httpsのようになります:// docs.python.org/3 /ライブラリ/ unittest.mock.html' – mbieren

答えて

2

あなたはこのように、patchを使用することができます。

from unittest.mock import patch, MagicMock 

@patch('mypackage.mymodule.pymysql') 
def test(self, mock_sql): 
    self.assertIs(mypackage.mymodule.pymysql, mock_sql) 

    conn = Mock() 
    mock_sql.connect.return_value = conn 

    cursor  = MagicMock() 
    mock_result = MagicMock() 

    cursor.__enter__.return_value = mock_result 
    cursor.__exit___    = MagicMock() 

    conn.cursor.return_value = cursor 

    connectDB() 

    mock_sql.connect.assert_called_with(host='localhost', 
             user='user', 
             password='passwd', 
             db='db') 

    mock_result.execute.assert_called_with("sql request", ("user", "pass")) 
+0

私のPythonのバージョン2.7である。 "unittest.mock"はPython 3.3以降で利用できます。 – Mythri

+0

Python 2.7用のMockパッケージを使用することができます:https://pypi.python.org/pypi/mock – uwevil

0

ハードコードされた値を返すスタブと呼ばれる一連の偽のデータベースが必要です。テストの間、これらのスタブは実際のデータベースの代わりに使用されます。私はPythonに慣れていませんが、C++でこれを行う方法の1つは、オブジェクトをコンストラクタパラメータとしてデータベースを受け取るようにすることです。実動コードでは、スタブをテストする際に実際のデータベースパラメータを使用します。これは、コンストラクターが共通基本クラスへのポインターを期待しているために実行できます。 Pythonのために書かれていなくても、Roy Osheroveの最初の章:ユニットテストの芸術を読むことをお勧めします。この本は、なぜこれらの偽のデータベースがスタブで、モックではないのかを明確に説明しています。

0

あなたは、テストが重要であるという最も魅力的な理由の1つを再発見しました。これは、デザインが悪いときにあなたに伝えます。

少し違って言えば、テスト容易性は、品質の優れた一次プロキシです。次のことを考えてみましょう:

class DB(object): 
    def __init__(self, **credentials): 
     self._connect = partial(pymysql.connect, **credentials) 

    def query(self, q_str, params): 
     with self._connect as conn: 
      with conn.cursor() as cur: 
       cur.execute(q_str, params) 
       return cur.fetchall() 

# now for usage 

test_credentials = { 
    # use credentials to a fake database 
} 

test_db = DB(**test_credentials) 
test_db.query(write_query, list_of_fake_params) 
results = test_db.query(read_query) 
assert results = what_the_results_should_be 

あなたは複数のデータベースを扱う場合は、APIの類似性に応じて、多型またはを使用することができ、特定のDBは、あなたのオブジェクトへのコンストラクタのパラメータとなります。

関連する問題