Python / Pytest: how test a CLI command?

Viewed 712

I have a simple class with Flask_restx:

from flask_restx import Namespace, Resource

from flask import current_app

ping_namespace = Namespace("ping")


class Ping(Resource):
    def get(self):
        return {
            "status": "success",
            "message": "system up and running",
            "api_version": current_app.config["APP_VERSION"],
        }

    def pingFromCommand():
        print(current_app.config["APP_VERSION"])


ping_namespace.add_resource(Ping, "")

This is the simple command in manage.py

[...]
app = create_app()
cli = FlaskGroup(create_app=create_app)

from project.batch.v2.ping.ping import Ping

@cli.command('ping')
def ping():
    Ping.pingFromCommand()

If I run from command line, I get the desiderated result:

(env) $ python manage.py ping
(env) $ 2.0.0

I know how write tests for API resources with pytest, but I don't know how can I write a test for the pingFromCommand method.

I did try:

from project.batch.v2.ping.ping import Ping

def test_ping_command(test_app):
    assert Ping.pingFromCommand() == "0.0.0"

But I get

>       assert Ping.pingFromCommand() == "0.0.0"
E       AssertionError: assert None == '0.0.0'
E        +  where None = <function Ping.pingFromCommand at 0x7fd41c619160>()
E        +    where <function Ping.pingFromCommand at 0x7fd41c619160> = Ping.pingFromCommand

Someone can help me or address me? Thank you in advance.

1 Answers

In the pingFromCommand function, print is used to print the current app version. That function returns None which is what you get in the AssertionError.

You can update the function to return the app version

def pingFromCommand():
    return current_app.config["APP_VERSION"]

Or you might be able to use capsys fixture provided by pytest which will capture standard output:

def test_ping_command(capsys, test_app):
    Ping.pingFromCommand()
    captured = capsys.readouterr()  # Capture output
    assert captured.out == "0.0.0"  # Assert stdout
Related