单元测试框架:在新进程中运行测试

1 投票
3 回答
1894 浏览
提问于 2025-04-16 22:04

我编写了一个图形界面应用程序,它使用了单元测试框架。这个应用程序会把找到的所有单元测试显示在一个树状视图中。如果你点击某个单元测试的名字,程序就会运行这个测试并显示结果。它运行得很好!

但是现在我想让每个测试用例在一个新的进程中运行。我创建了一个“工作线程”(使用了线程模块),但这个线程还是在同一个进程中运行。

使用“多进程”模块可以解决这个问题,但我在实现过程中遇到了一些问题。我把我的“测试执行代码”放在一个单独的函数里,然后尝试了:

item = self.GetSelection()
name = self.GetItemText(item)
p = multiprocessing.Process(target=ExecuteTest, args=(name, item))
p.daemon = True
p.start()

但随后我遇到了错误。

Traceback (most recent call last):
  File "C:\a\b\c\hhh\a.py", line 577, in OnLeftDClick
    p.start()
  File "C:\Python26\lib\multiprocessing\process.py", line 104, in start
    self._popen = Popen(self)
  File "C:\Python26\lib\multiprocessing\forking.py", line 239, in __init__
    dump(process_obj, to_child, HIGHEST_PROTOCOL)
  File "C:\Python26\lib\multiprocessing\forking.py", line 162, in dump
    ForkingPickler(file, protocol).dump(obj)
  File "C:\Python26\lib\pickle.py", line 224, in dump
    self.save(obj)
  File "C:\Python26\lib\pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Python26\lib\pickle.py", line 419, in save_reduce
    save(state)
  File "C:\Python26\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python26\lib\pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python26\lib\pickle.py", line 681, in _batch_setitems
    save(v)
  File "C:\Python26\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python26\lib\pickle.py", line 548, in save_tuple
    save(element)
  File "C:\Python26\lib\pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Python26\lib\pickle.py", line 419, in save_reduce
    save(state)
  File "C:\Python26\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python26\lib\pickle.py", line 649, in save_dict
    self._batch_setitems(obj.iteritems())
  File "C:\Python26\lib\pickle.py", line 686, in _batch_setitems
    save(v)
  File "C:\Python26\lib\pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "C:\Python26\lib\pickle.py", line 396, in save_reduce
    save(cls)
  File "C:\Python26\lib\pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "C:\Python26\lib\pickle.py", line 748, in save_global
    (obj, module, name))
pickle.PicklingError: Can't pickle <type 'PySwigObject'>: it's not found as __builtin__.PySwigObject

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Python26\lib\multiprocessing\forking.py", line 342, in main
    self = load(from_parent)
  File "C:\Python26\lib\pickle.py", line 1370, in load
    return Unpickler(file).load()
  File "C:\Python26\lib\pickle.py", line 858, in load
    dispatch[key](self)
  File "C:\Python26\lib\pickle.py", line 880, in load_eof
    raise EOFError
EOFError

有没有人知道该怎么解决?

3 个回答

-1

使用 fork 来创建一个子进程。这需要你做一些工作,但可以实现。

顺便提一下:多进程模块是通过 fork 实现的。


更新:仔细查看你的代码后,发现 item 这个变量是不能被序列化的(这个词可以用吗?)。我觉得你不需要它,因为你可以用更简单的东西替代它(比如一个值之类的)。

0

我建议你写一个单独的脚本来运行测试,然后你可以用 subprocess 模块来调用这个脚本,并告诉它要运行哪些测试。

这样做的好处是,你可以在持续集成服务器、夜间构建或者其他不需要图形界面的批处理流程中使用同一个脚本。

1

显然,你正在尝试“腌制”一些不能被腌制的东西(看起来是一个wx对象)。试着只使用“简单”的对象作为参数(也就是说,不要里面有图形对象),这样应该会更顺利。你也可以看看Python的nose单元测试库,它可以让你自动在多个进程中运行测试。

撰写回答