使用python包装的c++SWIG模拟输入

2024-06-11 17:24:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我不熟悉swig和python单元测试。在

这就是我要做的。我有一个需要用户输入的c++函数。使用SWIG将C++代码封装到Python代码中。我尝试使用pythons unittest模块来模拟输入。我试着嘲笑内置输入用c++编写我自己的基本函数,只返回一个字符串,然后模仿它。在

嘲笑内置输入当我在c++代码中找到std::cin时仍然挂起。并且模拟返回字符串的函数时,不返回模拟的返回值。在

我的猜测是由于某种原因,我不能模仿函数的返回值,因为它实际上是c++代码,而不是真正的python。在

下面是我使用的一些示例代码:

c++I可以包含头文件是需要的,但它非常简单。在

#include "MockTest.h"
#include <iostream>
#include <string>

MockTest::MockTest() {}

std::string MockTest::getInput()
{
    std::string name;
    std::cout << "Enter you name" << std::endl;
    name = this->mockInput("hi"); //std::cin >> name;
    std::string toReturn = "Hello " + name + " person";
    return toReturn;
}

std::string MockTest::mockInput(std::string input)
{ 
    return input;
}

swig接口文件:

^{pr2}$

python测试脚本

from unittest.mock import patch
from unittest import TestCase
import unittest

import MockTest


class Test(TestCase):

    @patch('builtins.input', return_value="Will")
    def test_Mocktest(self, input):
        self.assertEqual(MockTest.MockTest().getInput(), 'Hello Will person')

    @patch('MockTest.MockTest.mockInput', return_value="Will")
    def test_Mocktest2(self, mockInput):
        self.assertEqual(MockTest.MockTest().getInput(), 'Hello Will person')

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

Tags: 函数代码nameimportselfinputstringreturn
1条回答
网友
1楼 · 发布于 2024-06-11 17:24:40

在一个愚蠢的错误上花了一个小时之后:

  • 生成的模块是不完整的这一事实(链接器在没有向其提供MockTest对象时,并没有抱怨未定义的符号)
  • 最后,因为我忘记在MockTest.h中的类成员之前添加public:。。。十: ((()
<> P>和对实际问题的更多时间的研究,我最终得出结论:问题不是因为EMS> C++ +EEM>语言(至少不是直接),而是它在 SWIG <强>中间层。

详情

在模块MockTest!!)中定义了MockTest类(其mockInput方法返回值patch)是在模块MockTest中定义的!!!那是MockTest.py!!!)它是由Swig自动生成的(我的例子中的命令是swig -o MockTest_wrap.cpp -python -c++ MockTest.i)。它的定义如下:

class MockTest(_object):
    __swig_setmethods__ = {}
    __setattr__ = lambda self, name, value: _swig_setattr(self, MockTest, name, value)
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, MockTest, name)
    __repr__ = _swig_repr

    def __init__(self):
        this = _MockTest.new_MockTest()
        try:
            self.this.append(this)
        except __builtin__.Exception:
            self.this = this
    __swig_destroy__ = _MockTest.delete_MockTest
    __del__ = lambda self: None

    def getInput(self):
        return _MockTest.MockTest_getInput(self)

    def mockInput(self, input):
        return _MockTest.MockTest_mockInput(self, input)

正如您可能猜到的,<强> >< /St>>{CD3>}是{{4+C++>EEM >(其名称为^ {CD9>}),并且由原生模块导出:^ {< CD10>}:在EM>MOCSTETER中定义的本机名是^ {CD11>}包装.cpp)。当然,由于getInput调用MockTest_getInputpatchingmockInput(Python包装器)没有任何效果(就像您将其主体修改为return "123")。

下面是我准备的一些示例代码,可以更好地说明这种行为(正如我在评论中提到的,我使用的是python3.5.4)。请忽略最后3行代码并输出,直到您阅读下一段:

^{pr2}$

以及输出:

c:\Work\Dev\StackOverflow\q45934545>"c:\Install\x64\Python\Python\3.5\python.exe" dummy.py
Enter you name
`mock_test.getInput()` returned: "Hello hi person"
`mock_test.mockInput("argument passed to `MockTest.mockInput`")` returned: "value overridden by `patch`"

Don't mind the following output for now...

Enter you name:
`mock_test.getInput()` returned: "Hello hi person"
`mock_test.mockInput("argument passed to `MockTest.mockInput`")` returned: "value overridden by `patch`"

然后我进一步尝试patchMockTest._MockTest.MockTest_mockInput,但是我得到了相同的输出,因为我没有{}MockTest::mockInput(来自模拟测试.cpp)但是_wrap_MockTest_mockInput(来自MocTest)_包装.cpp)。

下面是一个表,其中所有的层在 C++ +eEM>代码和 python ^ ^ }(对于{{CD12>}完全相同):

mockInput layers

getInput调用mockInput第0层)时,patch应该发生,但不幸的是,这不适用于Python

我想到的1st解决方案是直接patching getInput(第1层)(如果它在很多地方使用的话)。

相关问题 更多 >