How to mock argparse with pytest in bigger Python cli application

38 Views Asked by At

I'm working on the following application: https://github.com/TobiWo/eth-duties

I didn't include unit-tests from the beginning which is bad, I know but I wanted to concentrate on the functionality. Anyway, I want to add unit-tests now but I have big issues in doing so.

I already adapted a lot of stuff which can be found on this feature branch. Since I'm working with poetry I invoke pytest using poetry run pytest --cov=duties tests/. I could run a basic unit test (tests/protocol/test_connection.py). However, the second test I tried (tests/protocol/test_ethereum.py) failed and revealed a much bigger issue with regards to argparse. I try to describe the issue as detailed as I can:

  1. In my test file I want to test this function
  2. In the testfile you can see that I want to mock the function send_beacon_api_request
  3. However, this function is imported from module duties.protocol.request and within this module I also import the BeaconNode class which is then used within send_beacon_api_request or in one of the called private functions respectively. The issue is that the BeaconNode class imports my parsed arguments
  4. Now when I run the test I get the following error from pytest:
tests/protocol/test_ethereum.py:5: in <module>
    from duties.protocol.ethereum import get_current_slot
duties/protocol/ethereum.py:12: in <module>
    from duties.protocol.request import CalldataType, send_beacon_api_request
duties/protocol/request.py:18: in <module>
    beacon_node = BeaconNode()
duties/protocol/connection.py:19: in __init__
    self.__arguments = get_arguments()
duties/cli/arguments.py:305: in get_arguments
    arguments = __get_raw_arguments()
duties/cli/arguments.py:192: in __get_raw_arguments
    return parser.parse_args()
/home/towo/miniconda3/envs/poetry-py312/lib/python3.12/argparse.py:1894: in parse_args
    self.error(msg % ' '.join(argv))
/home/towo/miniconda3/envs/poetry-py312/lib/python3.12/argparse.py:2655: in error
    self.exit(2, _('%(prog)s: error: %(message)s\n') % args)
/home/towo/miniconda3/envs/poetry-py312/lib/python3.12/argparse.py:2642: in exit
    _sys.exit(status)
E   SystemExit: 2
-------------------------------------------------------------------------------------------------------- Captured stderr ---------------------------------------------------------------------------------------------------------
usage: eth-duties [...options]
eth-duties: error: unrecognized arguments: --cov=duties tests/

It looks like that I also need to mock argparse which I already tried. I know that I need to mock the get_arguments function based on the module I want to test. Same thing is working here. But this doesn't work and I get the above error. I might have a misunderstanding of pytest here so maybe someone can help.

I know it is hard to grasp because the application is pretty big already.

Since these kind of imports happening often times I'm pretty sure I will have this issue multiple times.

0

There are 0 best solutions below