Skip to content

Commit

Permalink
Add a less trivial test
Browse files Browse the repository at this point in the history
  • Loading branch information
rohanpm committed Jun 27, 2021
1 parent ad78696 commit 30c639c
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
dist/
.tox/
.coverage
.coverage*
25 changes: 17 additions & 8 deletions pytest_filecov/plugin/inotifywatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@


def do_inotifywait(
paths: List[str], ready: Event, on_stop: List[Callable], accessed: MutableSet[str]
paths: List[str],
ready: Event,
failed: List[Exception],
on_stop: List[Callable],
accessed: MutableSet[str],
):
cmd = ["inotifywait", "-m", "--csv", "-e", "access", "-r"]
cmd.extend(paths)
Expand All @@ -31,10 +35,12 @@ def do_inotifywait(
# a human-oriented message
while True:
line = proc.stderr.readline()
print("line", line)
if "Watches established" in line:
break
elif not line:
raise RuntimeError("inotifywait failed")
failed.append(RuntimeError("inotifywait did not initialize correctly"))
break

ready.set()

Expand All @@ -61,27 +67,30 @@ def __init__(self, watched_dirs: Sequence[str]):

def start(self):
ready = Event()
failed = []
self.thread = Thread(
name="inotifywait",
target=do_inotifywait,
kwargs={
"paths": self.watched_dirs,
"ready": ready,
"failed": failed,
"on_stop": self.on_stop,
"accessed": self.accessed,
},
daemon=True,
)
self.thread.start()

# TODO: complain if not ready
ready.wait(60.0)
assert ready.wait(60.0), "inotifywait timed out"

if failed:
self.thread.join(60.0)
raise failed[0]

def stop(self) -> Set[str]:
for cb in self.on_stop:
cb()
self.thread.join(5.0)
if self.thread.is_alive():
# TODO
print("thread didn't complete")
self.thread.join(60.0)
assert not self.thread.is_alive(), "inotifywait thread did not complete"
return self.accessed
20 changes: 20 additions & 0 deletions tests/fakecmd.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# A command which does whatever certain env vars tell it to do,
# used from within some tests
from os import environ
import sys
from base64 import b64decode


if __name__ == "__main__":
infix = sys.argv[1].upper()
stdout = b64decode(environ.get(f"FAKECMD_{infix}_STDOUT") or "")
stderr = b64decode(environ.get(f"FAKECMD_{infix}_STDERR") or "")
exitcode = int(environ.get(f"FAKECMD_{infix}_EXIT") or "0")

if stdout:
sys.stdout.buffer.write(stdout)
sys.stdout.buffer.flush()
if stderr:
sys.stderr.buffer.write(stderr)
sys.stderr.buffer.flush()
sys.exit(exitcode)
2 changes: 0 additions & 2 deletions tests/test_import.py

This file was deleted.

123 changes: 121 additions & 2 deletions tests/test_plugin.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
# High-level test of the entire plugin.
from unittest import mock
import argparse
import textwrap
import os
import sys
from functools import partial
from base64 import b64encode
import io

import py
from pluggy import PluginManager
import pytest

import pytest_filecov.plugin

FAKECMD_PATH = os.path.join(os.path.dirname(__file__), "fakecmd.py")


class FakePluginManager:
def __init__(self):
Expand All @@ -25,22 +35,131 @@ def option(self):
return self


def test_plugin_noop():
class FakeReporter:
def __init__(self):
self.buffer = io.StringIO()

def write_sep(self, sep, text):
self.buffer.write(f"{sep * 5} {text} {sep * 5}\n")

def write_line(self, text):
self.buffer.write(text + "\n")


def make_fakecmd_base(cmd, *, bindir, exitcode=0, stdout=b"", stderr=b""):
script = bindir.join(cmd)
script.write(f"#!/bin/sh\nexec {sys.executable} {FAKECMD_PATH} {cmd}\n")
script.chmod(0o755)

cmd = cmd.upper()

os.environ[f"FAKECMD_{cmd}_EXIT"] = str(exitcode)
os.environ[f"FAKECMD_{cmd}_STDOUT"] = b64encode(stdout).decode()
os.environ[f"FAKECMD_{cmd}_STDERR"] = b64encode(stderr).decode()


@pytest.fixture
def make_fakecmd(tmpdir: py.path.local, monkeypatch):
bindir = tmpdir.mkdir("bin")
monkeypatch.setenv("PATH", str(bindir) + ":" + os.environ["PATH"])

yield partial(make_fakecmd_base, bindir=bindir)


def get_plugin():
parser = mock.Mock(spec=["getgroup", "addoption"])
pm = FakePluginManager()
pytest_filecov.plugin.pytest_addoption(parser, pm)

# Should have registered
assert pm.registered

return pm.registered


def test_plugin_noop():
# Do a test in the case where no monitoring is requested
config = FakeConfig([])

plugin = pm.registered
plugin = get_plugin()

# These should all work and do effectively nothing
plugin.pytest_configure(config)
plugin.pytest_sessionstart(object())
plugin.pytest_sessionfinish(object())
assert plugin.pytest_report_header(object(), object()) == []
plugin.pytest_terminal_summary(object())


def test_plugin_bad_inotifywait(make_fakecmd):
make_fakecmd("inotifywait", exitcode=23)

config = FakeConfig(["dir1", "dir2"])

plugin = get_plugin()

plugin.pytest_configure(config)

# This won't work since inotifywait is broken
with pytest.raises(Exception) as exc_info:
plugin.pytest_sessionstart(object())

assert "inotifywait did not initialize" in str(exc_info)


def test_plugin_typical(make_fakecmd):
make_fakecmd(
"inotifywait",
stderr=b"Watches established\n",
stdout=b"\n".join(
[
b"some/dir,ACCESS,file1",
b"some/dir,ACCESS,file2",
b"some/dir,WHATEVER,file2",
b"some/dir,ACCESS,file3",
]
)
+ b"\n",
)

make_fakecmd(
"git",
stdout=b"\x00".join([b"some/dir/file1", b"some/dir/file3", b"some/dir/file4"])
+ b"\x00",
)

config = FakeConfig(["some", "other"])

plugin = get_plugin()

plugin.pytest_configure(config)

# Should start OK
plugin.pytest_sessionstart(object())

# Should finish OK
plugin.pytest_sessionfinish(object())

# Should tell me what was monitored
assert plugin.pytest_report_header(object(), object()) == [
"filecov: some",
"filecov: other",
]

# Should output a report
reporter = FakeReporter()
plugin.pytest_terminal_summary(reporter)

assert (
reporter.buffer.getvalue().strip()
== textwrap.dedent(
"""
===== pytest-filecov report =====
Filename Covered?
-------- --------
some/dir/file1 1
some/dir/file3 1
some/dir/file4 0
"""
).strip()
)

0 comments on commit 30c639c

Please sign in to comment.