【问题标题】:Mocking the return value on pandas apply模拟 pandas 的返回值 apply
【发布时间】:2019-08-20 05:26:32
【问题描述】:

我试图模拟 pandas 应用函数的返回值,但似乎无法让它工作。

我正在尝试创建一个模拟返回对象(在这种情况下,我的函数返回一个 dict),然后从我在 pandas.apply 中调用的函数中获得该返回。我将该值放在单元测试的 @patch 装饰器中,但它仍然最终调用了真正的函数

def pandas_function():
    data = {'one thing': {0: 1, 1: 2, 2: 3, 3: 4},'second thing': {0: 0.1, 1: 0.2, 2: 1.0, 3: 2.0}}
    df = pd.DataFrame(data)
    val = df.apply(real_function, axis=1)
    return val

def real_function(row):
    return dict("foo": row['one thing'])

Unit test class:
def stub_foo():
    foo="test"
    return dict("foo":foo)


Unit test class:
@patch('package.module.real_function',return_value=stub_foo())
def pandas_test(self, stub_foo)
    expected = pd.Series(data={0: {'foo': "test"}, 1: {'foo': "test"}, 2: {'foo': "test"}, 3: {'foo': "test"}})
    real = class.pandas_function()
    assert_series_equal(expected, real)

运行测试时的响应:

AssertionError: Series are different

Series values are different (100.0 %)
[left]:  [{'foo': 'test'}, {'foo': 'test'}, {'foo': 'test'}, {'foo': 'test'}]
[right]: [{'foo': 1.0}, {'foo': 2.0}, {'foo': 3.0}, {'foo': 4.0}]

如何让 unittest 模拟来自 apply 函数的响应对象?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    这里有几件事,因为 bamdan 建议首先修复语法错误:

    def real_function(row):
        return {'foo': row['one thing']}
    
    def stub_foo():
        return {'foo':'test'}
    

    接下来,如果我错误地导入 real_function,我可以复制您的错误。假设你的 real_function 是在 functions.py 中定义的,你应该像这样导入它:

    import functions
    

    在此处查看相关文档:https://docs.python.org/3/library/unittest.mock.html#where-to-patch

    然后一个完整的例子是:

    functions.py的内容:

    def real_function(row):
        return {'foo': row['one thing']}
    

    test_pandas_function.py的内容:

    import pandas as pd
    from mock import patch
    
    import functions
    
    def pandas_function():
        data = {'one thing': {0: 1, 1: 2, 2: 3, 3: 4},'second thing': {0: 0.1, 1: 0.2, 2: 1.0, 3: 2.0}}
        df = pd.DataFrame(data)
        val = df.apply(functions.real_function, axis=1)
        return val
    
    def stub_foo():
        return {'foo':'test'}
    
    @patch('functions.real_function', return_value=stub_foo(), autospec=True)
    def test_pandas(my_mock):
        expected = pd.Series(data={0: {'foo': "test"}, 1: {'foo': "test"}, 2: {'foo': "test"}, 3: {'foo': "test"}})
        real = pandas_function()
        pd.testing.assert_series_equal(expected, real)
    

    请注意,我建议您在补丁中也设置autospec=True 标志,您应该阅读此内容。

    最后,我这里的例子只是一个独立的测试。如果您的测试是某个类的一部分,您将需要相应地调整代码。

    【讨论】:

      【解决方案2】:

      我认为真正的函数包含错误。至少在我尝试跑步时是这样。

      你应该这样做

      return {"foo": row['one thing']}
      

      希望对您有所帮助。

      【讨论】:

        猜你喜欢
        • 2017-09-09
        • 2014-06-28
        • 2022-01-16
        • 1970-01-01
        • 1970-01-01
        • 2021-03-16
        • 1970-01-01
        • 2015-12-15
        • 1970-01-01
        相关资源
        最近更新 更多