Skip to content
This repository has been archived by the owner on Oct 1, 2024. It is now read-only.

Commit

Permalink
Merge branch 'master' of github.com:darrenburns/ward into master
Browse files Browse the repository at this point in the history
  • Loading branch information
darrenburns committed Oct 7, 2021
2 parents f8ce9ce + 2a5d04b commit d573045
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 10 deletions.
2 changes: 1 addition & 1 deletion docs/source/guide/pyproject.toml.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ all of your Ward configuration should appear there:
path = ["unit_tests", "integration_tests"] # supply multiple paths using a list
capture-output = false # enable or disable output capturing (e.g. to use debugger)
order = "standard" # or 'random'
output-mode = "test-per-line" # or 'dots-global', 'dot-module'
test-output-style = "test-per-line" # or 'dots-global', 'dot-module'
fail-limit = 20 # stop the run if 20 fails occur
search = "my_function" # search in test body or description
progress-style = ["bar"] # display a progress bar during the run
11 changes: 10 additions & 1 deletion tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
as_list,
read_config_toml,
set_defaults_from_config,
validate_config_toml,
)


Expand Down Expand Up @@ -123,6 +124,14 @@ def _(tmp=temp_config_invalid):
read_config_toml(Path(tempfile.gettempdir()), tmp.name)


@test("validate_config_toml raises click.ClickException if conf key is invalid")
def _():
invalid_key = "orderr"
with raises(click.ClickException) as exc_info:
validate_config_toml({invalid_key: "the key here is invalid"})
assert invalid_key in str(exc_info.raised)


@test("as_list({arg}) returns {rv}")
def _(arg=each("x", 1, True, ["a", "b"]), rv=each(["x"], [1], [True], ["a", "b"])):
assert as_list(arg) == rv
Expand Down Expand Up @@ -175,6 +184,6 @@ def _(project_root: Path = fake_project_pyproject):
assert fake_context.default_map == {
"exclude": (str(project_root / "a" / "b"),),
"path": (str(project_root / "a"), str(project_root / "x" / "y")),
"some_other_config": ["hello", "world"],
"order": "hello world",
}
assert fake_context.params["config_path"] == project_root / "pyproject.toml"
2 changes: 1 addition & 1 deletion tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def fake_project_pyproject():
[tool.ward]
path = ["a/", "x/y"]
exclude = ["a/b/"]
some_other_config = ["hello", "world"]
order = "hello world"
"""
yield from make_project("pyproject.toml", content)

Expand Down
22 changes: 22 additions & 0 deletions ward/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import tomli

from ward._utilities import find_project_root
from ward.config import Config

_ConfigValue = Union[int, str, bool, Iterable[str]]
_ConfigDict = Dict[str, _ConfigValue]
Expand Down Expand Up @@ -74,6 +75,26 @@ def apply_multi_defaults(
return file_config_only


def validate_config_toml(conf: _ConfigDict) -> None:
valid_conf_keys = set(Config.__dataclass_fields__) # type: ignore[attr-defined]

# These keys are derived from pyproject.toml path so makes no sense
# to define them in the file itself
valid_conf_keys.remove("config_path")
valid_conf_keys.remove("project_root")

# The key for plugin configuration differs from attr name in the
# `Config` dataclass
valid_conf_keys.remove("plugin_config")
valid_conf_keys.add("plugins")

for conf_key in conf:
if conf_key not in valid_conf_keys:
raise click.ClickException(
f"Invalid key {conf_key!r} found in pyproject.toml"
)


def set_defaults_from_config(
context: click.Context,
param: click.Parameter,
Expand All @@ -97,6 +118,7 @@ def set_defaults_from_config(
return Path.cwd()

file_config = read_config_toml(project_root, _CONFIG_FILE)
validate_config_toml(file_config)

if file_config:
config_path: Optional[Path] = project_root / _CONFIG_FILE
Expand Down
12 changes: 8 additions & 4 deletions ward/_suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,14 @@ def generate_test_runs(
yield test.fail_with_error(e)
continue
for generated_test in generated_tests:
yield generated_test.run(self.cache, dry_run=dry_run)
self.cache.teardown_fixtures_for_scope(
Scope.Test, scope_key=generated_test.id
)
result = generated_test.run(self.cache, dry_run=dry_run)
try:
self.cache.teardown_fixtures_for_scope(
Scope.Test, scope_key=generated_test.id
)
except Exception as e:
result = test.fail_with_error(e)
yield result

if num_tests_per_module[test.path] == 0:
self.cache.teardown_fixtures_for_scope(
Expand Down
4 changes: 2 additions & 2 deletions ward/_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1211,11 +1211,11 @@ def add_fixture_dependencies_to_tree(

def add_fixture_usages_by_tests_to_tree(node: Tree, used_by: Iterable[Test]) -> None:
grouped_used_by = group_by(used_by, key=lambda t: t.description)
for idx, (description, tests) in enumerate(grouped_used_by.items()):
for description, tests in grouped_used_by.items():
test = tests[0]
loc = format_test_location(test)
sep = f" [{len(tests)}]" if len(tests) > 1 else ""
node.add(f"[muted]{loc}{sep}[/muted] {test.description}")
node.add(f"[muted]{loc}{sep}[/muted] {description}")


def make_text_for_fixture(fixture: Fixture, show_scope: bool) -> Text:
Expand Down
2 changes: 1 addition & 1 deletion ward/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def teardown(self):
"""
# Suppress because we can't know whether there's more code
# to execute below the yield.
with suppress(RuntimeError, StopIteration, StopAsyncIteration):
with suppress(StopIteration, StopAsyncIteration):
if self.is_generator_fixture and self.gen:
next(self.gen)
elif self.is_async_generator_fixture and self.gen:
Expand Down

0 comments on commit d573045

Please sign in to comment.