Skip to content

Commit

Permalink
fix: issue causing ape test -w not to work (non-string arugments) (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey authored Sep 11, 2024
1 parent 203e63d commit d0eb2a7
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 14 deletions.
34 changes: 20 additions & 14 deletions src/ape_test/_cli.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import subprocess
import sys
import threading
import time
from collections.abc import Sequence
from datetime import datetime, timedelta
from pathlib import Path
from subprocess import run as run_subprocess

import click
import pytest
Expand Down Expand Up @@ -58,16 +57,16 @@ def process_event(self, event: events.FileSystemEvent) -> None:
emit_trigger()


def _run_ape_test(pytest_args):
return subprocess.run(["ape", "test", *pytest_args])
def _run_ape_test(*pytest_args):
return run_subprocess(["ape", "test", *[f"{a}" for a in pytest_args]])


def _run_main_loop(delay: float, pytest_args: Sequence[str]) -> None:
def _run_main_loop(delay: float, *pytest_args: str) -> None:
global trigger

now = datetime.now()
if trigger and now - trigger > timedelta(seconds=delay):
_run_ape_test(pytest_args)
_run_ape_test(*pytest_args)

with trigger_lock:
trigger = None
Expand Down Expand Up @@ -133,25 +132,22 @@ def _validate_pytest_args(*pytest_args) -> list[str]:
@click.argument("pytest_args", nargs=-1, type=click.UNPROCESSED)
def cli(cli_ctx, watch, watch_folders, watch_delay, pytest_args):
if watch:
event_handler = EventHandler()

observer = Observer()
event_handler = _create_event_handler()
observer = _create_observer()

for folder in watch_folders:
if folder.is_dir():
observer.schedule(event_handler, folder, recursive=True)

else:
cli_ctx.logger.warning(f"Folder '{folder}' doesn't exist or isn't a folder.")

observer.start()
pytest_args = _validate_pytest_args(pytest_args)
pytest_args = _validate_pytest_args(*pytest_args)

try:
_run_ape_test(pytest_args)

_run_ape_test(*pytest_args)
while True:
_run_main_loop(watch_delay, pytest_args)
_run_main_loop(watch_delay, *pytest_args)

finally:
observer.stop()
Expand All @@ -162,3 +158,13 @@ def cli(cli_ctx, watch, watch_folders, watch_delay, pytest_args):
if return_code:
# only exit with non-zero status to make testing easier
sys.exit(return_code)


def _create_event_handler():
# Abstracted for testing purposes.
return EventHandler()


def _create_observer():
# Abstracted for testing purposes.
return Observer()
28 changes: 28 additions & 0 deletions tests/integration/cli/test_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,31 @@ def test_fails():
actual = str(result.stdout)
assert secret in actual
assert "__FAIL__" in actual


@skip_projects_except("with-contracts")
def test_watch(mocker, integ_project, runner, ape_cli):
mock_event_handler = mocker.MagicMock()
event_handler_patch = mocker.patch("ape_test._cli._create_event_handler")
event_handler_patch.return_value = mock_event_handler

mock_observer = mocker.MagicMock()
observer_patch = mocker.patch("ape_test._cli._create_observer")
observer_patch.return_value = mock_observer

run_subprocess_patch = mocker.patch("ape_test._cli.run_subprocess")
run_main_loop_patch = mocker.patch("ape_test._cli._run_main_loop")
run_main_loop_patch.side_effect = SystemExit # Avoid infinite loop.

# Only passing `-s` so we have an extra arg to test.
result = runner.invoke(ape_cli, ("test", "--watch", "-s"))
assert result.exit_code == 0

# The observer started, then the main runner exits, and the observer stops + joins.
assert mock_observer.start.call_count == 1
assert mock_observer.stop.call_count == 1
assert mock_observer.join.call_count == 1

# NOTE: We had a bug once where the args it received were not strings.
# (wasn't deconstructing), so this check is important.
run_subprocess_patch.assert_called_once_with(["ape", "test", "-s"])

0 comments on commit d0eb2a7

Please sign in to comment.