Python Unit Test: ¿Cómo realizar una prueba unitaria del módulo que contiene las operaciones de la base de datos?

Estoy utilizando la biblioteca cliente pymysql para conectarme a la base de datos real. Tengo una función en el módulo, donde me conecto a la base de datos utilizando pymysql y hago solo operaciones de inserción de base de datos. ¿Cómo probar esta función en Python sin llegar a la base de datos real?

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, ('newuser@some.com', 'newpassword')) connection.commit() 

Mi versión de python es 2.7.

Puedes usar el patch , así:

 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")) 

Necesita una serie de bases de datos falsas, llamadas apéndices, que devuelven valores codificados. Durante la prueba, estos apéndices se utilizan en lugar de la base de datos real. No estoy familiarizado con Python, pero una forma de hacerlo en C ++ es hacer que su objeto reciba la base de datos como un parámetro de constructor. En el código de producción se usa un parámetro de base de datos real, en la prueba del código auxiliar. Esto se puede hacer porque el constructor espera un puntero a una clase base común. Incluso si no está escrito para Python, sugiero leer los primeros capítulos de Roy Osherove: El arte de la prueba de unidad. El libro explica claramente por qué estas bases de datos falsas son apéndices y no simulacros.

Acaba de redescubrir una de las razones más convincentes por las que las pruebas son importantes: le dice cuándo el diseño es malo.

Para decirlo de forma ligeramente diferente, la capacidad de prueba es un buen proxy de primer orden para la calidad . Considera lo siguiente:

 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 

Si trabaja con múltiples bases de datos, puede usar polymorphism o, dependiendo de la similitud de la API, haga que la base de datos específica sea un parámetro de construcción para su objeto.