自定义 GNU radio python 块中引发异常的单元测试

Unit test for exception raised in custom GNU radio python block

我创建了一个自定义 python 同步块用于 gnuradio 流程图。该块测试无效输入,如果找到,则引发 ValueError 异常。我想创建一个单元测试来验证当块确实收到无效输入数据时是否引发了异常。

作为此块基于 python 的质量检查测试的一部分,我创建了一个流程图,以便该块接收无效数据。当我 运行 测试时,该块似乎确实引发异常但随后挂起。

对此进行测试的合适方法是什么?这是一个最小的工作示例:

#!/usr/bin/env python

import numpy as np

from gnuradio import gr, gr_unittest, blocks

class validate_input(gr.sync_block):

    def __init__(self):
        gr.sync_block.__init__(self,
            name="validate_input",
            in_sig=[np.float32],
            out_sig=[np.float32])

        self.max_input = 100

    def work(self, input_items, output_items):
        in0 = input_items[0]

        if (np.max(in0) > self.max_input):
           raise ValueError('input exceeds max.')

        validated_in = output_items[0]
        validated_in[:] = in0

        return len(output_items[0])

class qa_validate_input (gr_unittest.TestCase):

    def setUp (self):
        self.tb = gr.top_block ()

    def tearDown (self):
        self.tb = None

    def test_check_valid_data(self):

        src_data = (0, 201, 92)

        src = blocks.vector_source_f(src_data)
        validate = validate_input()
        snk = blocks.vector_sink_f()

        self.tb.connect (src, validate)
        self.tb.connect (validate, snk)

        self.assertRaises(ValueError, self.tb.run)

if __name__ == '__main__':
    gr_unittest.run(qa_validate_input, "qa_validate_input.xml")

产生:

DEPRECATED: Using filename with gr_unittest does no longer have any effect.
handler caught exception: input exceeds max.
Traceback (most recent call last):
  File "/home/xxx/devel/gnuradio3_8/lib/python3.6/dist-packages/gnuradio/gr/gateway.py", line 60, in eval
    try: self._callback()
  File "/home/xxx/devel/gnuradio3_8/lib/python3.6/dist-packages/gnuradio/gr/gateway.py", line 230, in __gr_block_handle
    ) for i in range(noutputs)],
  File "qa_validate_input.py", line 21, in work
    raise ValueError('input exceeds max.')
ValueError: input exceeds max.
thread[thread-per-block[1]: <block validate_input(2)>]: SWIG director method error. Error detected when calling 'feval_ll.eval'
^CF
======================================================================
FAIL: test_check_valid_data (__main__.qa_validate_input)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "qa_validate_input.py", line 47, in test_check_valid_data
    self.assertRaises(ValueError, self.tb.run)
AssertionError: ValueError not raised by run

----------------------------------------------------------------------
Ran 1 test in 1.634s

FAILED (failures=1)

top_block的run()函数不直接调用块的work()函数,而是启动内部任务调度器及其线程并等待它们完成。

对块中的错误处理进行单元测试的一种方法是直接调用 work() 函数

    def test_check_valid_data(self):
        src_data = [[0, 201, 92]]
        output_items = [[]]

        validate = validate_input()
        self.assertRaises(ValueError, lambda: validate.work(src_data, output_items))