用Python模拟一个MySQL数据库

19

我使用Anaconda发行版的Python 3.4版本。在这个发行版中,我找到了pymysql库来连接位于另一台计算机上的现有MySQL数据库。

import pymysql
config = {
      'user': 'my_user',
      'passwd': 'my_passwd',
      'host': 'my_host',
      'port': my_port
    }

    try:
        cnx = pymysql.connect(**config)
    except pymysql.err.OperationalError : 
        sys.exit("Invalid Input: Wrong username/database or password")

我现在想为我的应用程序编写测试代码,在每个测试用例的setUp中创建一个非常小的数据库,最好是内存中的。然而,当我尝试使用pymysql时,它无法建立连接。

def setUp(self):
    config = {
      'user': 'test_user',
      'passwd': 'test_passwd',
      'host': 'localhost'
    }
    cnx = pymysql.connect(**config)

pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 61] Connection refused)")

我一直在谷歌上搜索,找到了一些关于SQLiteMySQLdb的东西。 我有以下问题:
  1. sqlite3MySQLdb适合快速创建内存数据库吗?
  2. 如何在Anaconda软件包中安装MySQLdb
  3. 是否有一个在setUp中创建测试数据库的示例?这是一个好主意吗?

我没有在本地计算机上运行MySQL服务器。


2
答案可能是在本地运行一个mysql数据库。SQLite与mysql有许多不同之处,因此用SQLite替换mysql并不是一个好的测试方法。 - Philip Couling
2个回答

18

你可以使用 testing.mysqld (pip install testing.mysqld) 来模拟一个mysql数据库。

由于一些嘈杂的错误日志会出现,我在测试时喜欢使用这个设置:

import testing.mysqld
from sqlalchemy import create_engine

# prevent generating brand new db every time.  Speeds up tests.
MYSQLD_FACTORY = testing.mysqld.MysqldFactory(cache_initialized_db=True, port=7531)


def tearDownModule():
    """Tear down databases after test script has run.
    https://docs.python.org/3/library/unittest.html#setupclass-and-teardownclass
    """
    MYSQLD_FACTORY.clear_cache()


class TestWhatever(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        cls.mysql = MYSQLD_FACTORY()
        cls.db_conn = create_engine(cls.mysql.url()).connect()

    def setUp(self):
        self.mysql.start()
        self.db_conn.execute("""CREATE TABLE `foo` (blah)""")

    def tearDown(self):
        self.db_conn.execute("DROP TABLE foo")

    @classmethod
    def tearDownClass(cls):
        cls.mysql.stop()  # from source code we can see this kills the pid

    def test_something(self):
        # something useful

10

pymysql、MySQLdb和sqlite都需要一个真实的数据库来连接。如果你只是想测试你的代码,应该在你想要测试的模块上模拟pymysql模块,并相应地使用它(在你的测试代码中,你可以设置模拟对象返回预定义SQL语句的硬编码结果)。

请查看本机Python模拟库的文档: https://docs.python.org/3/library/unittest.mock.html

或者,对于Python 2:https://pypi.python.org/pypi/mock


2
似乎我想要的是不可能实现的。目标并非嘲讽pymysql,而是想测试代码是否可以在“真实”的SQL数据库上运行。这个数据库不一定要有MySQL的所有特性,但应该可以通过pymysql与其通信。在每台运行测试的机器上本地安装MySQL服务器并不切实际。 - physicalattraction
2
SQLite是一个“真正”的数据库,而pymysql和MySQLdb只是连接到MySQL的连接器。 - Air
请注意,在“您必须运行测试的所有机器”中,您无需在所有机器上都安装MySQL - 所有这些机器都可以连接到同一个MySQL数据库,只要提供连接URL即可。 - jsbueno
7
给未来的读者:这是Docker容器的一个用例。它简化了这种类型的集成测试,并且很容易找到相关文档。 - Scott Prive

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接