Skip to content
Snippets Groups Projects
Commit 455b2d40 authored by Florian Bruhin's avatar Florian Bruhin
Browse files

tests: Refactor to use custom ExpectedConsole

parent 11626d41
No related branches found
No related tags found
No related merge requests found
import os
import io
import textwrap
import pathlib
import datetime
from typing import cast
import rich.console
import rich.panel
import pytest
import typer.testing
import click.testing
from pytest_httpx import HTTPXMock
from pytest_golden.plugin import GoldenTestFixture
from typer.testing import CliRunner
from time_machine import TimeMachineFixture
from taas_client import cli
runner = CliRunner()
runner = typer.testing.CliRunner()
FROZEN_TIME = datetime.datetime(2022, 10, 12, 13, 37).astimezone()
class CaptureConsole(rich.console.Console):
class ExpectedConsole:
"""Object to store expected prints.
This is used to make testing rich output easier."""
def __init__(self):
super().__init__(file=io.StringIO())
self._file = io.StringIO()
self._console = rich.console.Console(file=self._file)
self.exit_code: int | None = None
def getvalue(self) -> str:
f = cast(io.StringIO, self.file)
return f.getvalue()
def check(self, result: click.testing.Result) -> None:
print(result.output)
assert result.exit_code == self.exit_code
assert result.output == self._file.getvalue()
def error_panel(self, text: str) -> rich.panel.Panel:
return rich.panel.Panel(text, title="Error", title_align="left")
def error_panel(self, text: str) -> None:
self._console.print(rich.panel.Panel(text, title="Error", title_align="left"))
def usage_lines(self) -> str:
return (
"Usage: upload-file [OPTIONS] NOTEBOOK [URL]\n"
"Try 'upload-file --help' for help."
)
def line(self, text: str) -> None:
self._console.print(text)
def usage_lines(self) -> None:
self._console.print("Usage: upload-file [OPTIONS] NOTEBOOK [URL]")
self._console.print("Try 'upload-file --help' for help.")
@pytest.fixture
def console() -> CaptureConsole:
return CaptureConsole()
def expected() -> ExpectedConsole:
return ExpectedConsole()
class TestArgumentParsing:
def test_no_args(self, console: CaptureConsole) -> None:
def test_no_args(self, expected: ExpectedConsole) -> None:
result = runner.invoke(cli.app, [])
print(result.stdout)
console.print(console.usage_lines())
console.print(console.error_panel("Missing argument 'NOTEBOOK'."))
expected.usage_lines()
expected.error_panel("Missing argument 'NOTEBOOK'.")
expected.exit_code = 2
assert result.exit_code == 2
assert result.stdout == console.getvalue()
expected.check(result)
def test_inexistent_file(self, tmp_path: pathlib.Path, console: CaptureConsole) -> None:
def test_inexistent_file(
self, tmp_path: pathlib.Path, expected: ExpectedConsole
) -> None:
nb_path = tmp_path / "nb.ipynb"
result = runner.invoke(cli.app, [str(nb_path)])
print(result.stdout)
msg = f"Invalid value for 'NOTEBOOK': File '{nb_path}' does not exist."
console.print(console.usage_lines())
console.print(console.error_panel(msg))
expected.usage_lines()
expected.error_panel(msg)
expected.exit_code = 2
assert result.exit_code == 2
assert result.stdout == console.getvalue()
expected.check(result)
def test_dir(self, tmp_path: pathlib.Path, console: CaptureConsole) -> None:
def test_dir(self, tmp_path: pathlib.Path, expected: ExpectedConsole) -> None:
nb_path = tmp_path / "nb.ipynb"
nb_path.mkdir()
result = runner.invoke(cli.app, [str(nb_path)])
print(result.stdout)
msg = f"Invalid value for 'NOTEBOOK': File '{nb_path}' is a directory."
console.print(console.usage_lines())
console.print(console.error_panel(msg))
expected.usage_lines()
expected.error_panel(msg)
expected.exit_code = 2
assert result.exit_code == 2
assert result.stdout == console.getvalue()
expected.check(result)
def test_unreadable(self, tmp_path: pathlib.Path, console: CaptureConsole) -> None:
def test_unreadable(
self, tmp_path: pathlib.Path, expected: ExpectedConsole
) -> None:
nb_path = tmp_path / "nb.ipynb"
nb_path.touch()
nb_path.chmod(0)
......@@ -90,30 +99,28 @@ class TestArgumentParsing:
pytest.skip("failed to make file unreadable") # pragma: no cover
result = runner.invoke(cli.app, [str(nb_path)])
print(result.stdout)
msg = f"Invalid value for 'NOTEBOOK': File '{nb_path}' is not readable."
console.print(console.usage_lines())
console.print(console.error_panel(msg))
expected.usage_lines()
expected.error_panel(msg)
expected.exit_code = 2
assert result.exit_code == 2
assert result.stdout == console.getvalue()
expected.check(result)
def test_wrong_location(tmp_path: pathlib.Path) -> None:
def test_wrong_location(tmp_path: pathlib.Path, expected: ExpectedConsole) -> None:
nb_path = tmp_path / "nb.ipynb"
nb_path.touch()
result = runner.invoke(cli.app, [str(nb_path)])
print(result.stdout)
expected = f"""
Refusing to submit file from unexpected location:
{nb_path}
Make sure you're not accidentally working in the 'Originale' folder!
"""
expected.line("Refusing to submit file from unexpected location: ")
expected.line(str(nb_path))
expected.line(
"Make sure you're not accidentally working in the 'Originale' folder!"
)
expected.exit_code = 1
assert result.exit_code == 1
assert result.stdout == textwrap.dedent(expected).lstrip("\n")
expected.check(result)
@pytest.fixture
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment