Python 单元测试 bug?

3
在这个简单的单元测试中,只能运行一个测试用例。当我注释掉任何一个测试用例时,剩下的测试运行通过,并且模块正常终止。当我允许两个测试用例都运行时,第一个用例通过,而第二个用例永远不会终止。模块永远不会终止。我创建了其他具有相同用例的模块,每个测试用例总是可以单独运行。
除了 unittest 中可能出现奇怪的 bug(通常不是正确的结论 - 我的代码总是罪魁祸首),我无法弄清楚发生了什么。
from glob import glob
from email import message_from_string
from database import login_info
import maildb
import unittest

import mysql.connector as DBC

db = DBC.connect(**login_info)
curs = db.cursor()

TBLDEF = """
CREATE TABLE message (
    msgID INTEGER AUTO_INCREMENT PRIMARY KEY,
    msgMessageID VARCHAR(128),
    msgText LONGTEXT
    )"""
FILESPEC = "C:/PythonData/*.eml"

class testRealEmail_traffic(unittest.TestCase):
    def setUp(self):
        """
        Reads arbitrary number of email messages and stores them
        in a brand new messages table.
        Destroys any previous table named message.
        """

        curs.execute("DROP TABLE IF EXISTS message")
        db.commit()
        curs.execute(TBLDEF)
        db.commit()

        files = glob(FILESPEC)
        self.msgids = {}
        self.message_ids = {}
        for f in files:
            ff = open(f)
            text = ff.read()
            msg = message_from_string(text)
            id = self.msgids[msg['message-id']] = maildb.store(msg)
            self.message_ids[id] = msg['message-id']

    def test_not_empty(self):
        """
        Make sure the setUp method created messages and loaded the table.
        """
        curs.execute("SELECT COUNT(*) FROM message")
        messagecount = curs.fetchone()[0]
        self.assertGreater(messagecount, 0, "Database message table is empty")

    def test_a_test(self):
        self.assertEqual(1,1)

if __name__ == "__main__":
    unittest.main()

这意味着我已经被 MySQL 中的“删除表”操作卡住了好几个小时。 - Lewis Levin
2
正如你所知,setUp在每个测试之前运行。我建议在setUp的每一行之前添加打印语句,看看哪一行出现了问题。 - Brian Rue
2
随机表名怎么样?这将允许您让MySQL在后台删除表格,然后在tearDown()中触发。此外,dbcurs是全局的看起来不对。我希望它们在setUp()中创建并附加到self上。保持打开连接和表引用可能会导致数据库中的开销和减速,因为它不能简单地丢弃数据。虽然我必须承认我对MySQL一无所知,所以我可能完全错了。 - Ulrich Eckhardt
这是一个元数据锁定问题,如此描述:http://www.chriscalender.com/?tag=innodb-locks。有点令人震惊的是,即使是选择操作也会导致元数据锁定。哇! - Lewis Levin
@Ulrich:你说得对,全局变量需要在setUp中定义db和curs。同时,被测试的代码连接到了同一个数据库并使用了全局变量。不确定问题出在哪里,但这会导致MySQL中有休眠进程。将连接和游标创建移动到实际函数中解决了这个问题。有人知道Python何时关闭连接吗? - Lewis Levin
显示剩余2条评论
1个回答

0
关于全局变量,你是正确的。db和curs需要在setUp中。另外,被测试的代码连接到了同一个数据库并使用了全局变量。不确定问题出在哪里,但这导致了MySQL中的睡眠进程。将连接和游标创建移动到实际函数中解决了问题。

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