flywire
flywire

Reputation: 1375

How to Test Pandas Function with Mutable Argument

How can I test a pandas function with a mutable argument? The function works in the program and test as shown but returns the None type in the test. It needs to test against the pandas DataFrame <class 'pandas.core.frame.DataFrame'>.

Two similar questions don't help much with writing the assert function:

Note: This is not a mutable default issue.

prog.py

import pandas as pd

def new_year(df):
    df.Class += 1
    # print(".", df)

df = pd.DataFrame({'Name':['Jack', 'Jill'], 'Class':[4, 5]})
new_year(df)
print(df)
(tst) E:\venv\tst>python prog.py
   Name  Class
0  Jack      5
1  Jill      6

test_prog.py

import unittest
import pandas as pd
from pandas._testing import assert_frame_equal
from prog import new_year

def test_new_year():
    df1 = pd.DataFrame({'Name':['Jack', 'Jill'], 'Class':[4, 5]})
    df2 = pd.DataFrame({'Name':['Jack', 'Jill'], 'Class':[5, 6]})
    assert_frame_equal(new_year(df1), df2)
(tst) E:\venv\tst>pytest -vv tests
=================================================== test session starts ===================================================
platform win32 -- Python 3.9.0, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- e:\venv\tst\scripts\python.exe
cachedir: .pytest_cache
rootdir: E:\venv\tst
collected 1 item

tests/test_prog.py::test_new_year FAILED                                                                             [100%]

======================================================== FAILURES =========================================================
______________________________________________________ test_new_year ______________________________________________________

    def test_new_year():
        df1 = pd.DataFrame({'Name':['Jack', 'Jill'], 'Class':[4, 5]})
        df2 = pd.DataFrame({'Name':['Jack', 'Jill'], 'Class':[5, 6]})
>       assert_frame_equal(new_year(df1), df2)

tests\test_prog.py:9:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

left = None, right =    Name  Class
0  Jack      5
1  Jill      6, cls = <class 'pandas.core.frame.DataFrame'>

    def _check_isinstance(left, right, cls):
        """
        Helper method for our assert_* methods that ensures that
        the two objects being compared have the right type before
        proceeding with the comparison.

        Parameters
        ----------
        left : The first object being compared.
        right : The second object being compared.
        cls : The class type to check against.

        Raises
        ------
        AssertionError : Either `left` or `right` is not an instance of `cls`.
        """
        cls_name = cls.__name__

        if not isinstance(left, cls):
>           raise AssertionError(
                f"{cls_name} Expected type {cls}, found {type(left)} instead"
            )
E           AssertionError: DataFrame Expected type <class 'pandas.core.frame.DataFrame'>, found <class 'NoneType'> instead

lib\site-packages\pandas\_testing.py:508: AssertionError
================================================= short test summary info =================================================
FAILED tests/test_parse_methods.py::test_clean_date - AssertionError: DataFrame Expected type <class 'pandas.core.frame.D...
FAILED tests/test_prog.py::test_new_year - AssertionError: DataFrame Expected type <class 'pandas.core.frame.DataFrame'>,...
=============================================== 1 failed in 0.91s ===============================================

Upvotes: 1

Views: 252

Answers (1)

Mustafa Aydın
Mustafa Aydın

Reputation: 18316

You can try returning the df in the new_year function:

def new_year(df):
    df.Class += 1
    return df

As it stands, the new_year function has no explicit return statement so it returns None and hence the AssertionError.

Upvotes: 1

Related Questions