Skip to content

Commit 51f3e7a

Browse files
Merge pull request #96 from F-Secure/working-directory-rts
feat: run tests from changes in workdir
2 parents 85cc145 + 07104f8 commit 51f3e7a

File tree

19 files changed

+452
-17
lines changed

19 files changed

+452
-17
lines changed

README.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@ Plugin is supposed to be used to execute tests related to changes done locally o
1616
To start using pytest-rts build of coverage DB is needed. For [Trunk Based Development](https://trunkbaseddevelopment.com/) mapping database from `master` branch should be used, for [A successful Git branching model](https://nvie.com/posts/a-successful-git-branching-model/) - `develop`
1717

1818
1. Install [pytest-cov](https://github.com/pytest-dev/pytest-cov) with `pip install pytest-cov`
19-
2. Execute `pytest --cov=[path to your package] --cov-context=test` which will run the entire test suite and build a mapping database in `.coverage` file
20-
3. Rename the coverage file `.coverage` produced by `pytest-cov` to your liking. Example: `mv .coverage pytest-rts-coverage`
19+
2. Create a `.coveragerc` file with the following contents inside to configure `pytest-cov`:
20+
```
21+
[run]
22+
relative_files = True
23+
```
24+
25+
3. Execute `pytest --cov=[path to your package] --cov-context=test` which will run the entire test suite and build a mapping database in `.coverage` file
26+
4. Rename the coverage file `.coverage` produced by `pytest-cov` to your liking. Example: `mv .coverage pytest-rts-coverage`
2127

2228
### Local usage
2329

pytest_rts/plugin.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
from _pytest.config.argparsing import Parser
77

88
from pytest_rts.pytest.runner_plugin import RunnerPlugin
9-
from pytest_rts.utils.common import get_existing_tests
9+
from pytest_rts.utils.common import get_existing_tests, get_tests_current
10+
from pytest_rts.utils.git import is_git_repo
1011

1112

1213
def pytest_addoption(parser: Parser) -> None:
@@ -26,11 +27,15 @@ def pytest_configure(config: Config) -> None:
2627
if not config.option.rts:
2728
return
2829

30+
if not is_git_repo():
31+
pytest.exit("pytest-rts: Cannot find a Git repository in the current folder", 2)
32+
2933
if not config.option.rts_coverage_db:
30-
pytest.exit("No coverage file provided", 2)
34+
pytest.exit("pytest-rts: No coverage file provided", 2)
3135

3236
if not os.path.exists(config.option.rts_coverage_db):
33-
pytest.exit("Provided coverage file does not exist", 2)
37+
pytest.exit("pytest-rts: Provided coverage file does not exist", 2)
3438

3539
existing_tests = get_existing_tests(config.option.rts_coverage_db)
36-
config.pluginmanager.register(RunnerPlugin(existing_tests))
40+
workdir_tests = get_tests_current(config.option.rts_coverage_db)
41+
config.pluginmanager.register(RunnerPlugin(existing_tests, workdir_tests))

pytest_rts/pytest/runner_plugin.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@
1212
class RunnerPlugin:
1313
"""Plugin class for pytest"""
1414

15-
def __init__(self, existing_tests: Set[str]) -> None:
15+
def __init__(self, existing_tests: Set[str], tests_from_changes: Set[str]) -> None:
1616
"""Set existing tests"""
1717
self.existing_tests = existing_tests
18+
self.tests_from_changes = tests_from_changes
1819

1920
def pytest_collection_modifyitems(
2021
self,
@@ -24,7 +25,9 @@ def pytest_collection_modifyitems(
2425
) -> None:
2526
"""Select only specific tests for running"""
2627
original_length = len(items)
27-
items[:] = filter_pytest_items(items, self.existing_tests)
28+
items[:] = filter_pytest_items(
29+
items, self.existing_tests, self.tests_from_changes
30+
)
2831
session.config.hook.pytest_deselected(
2932
items=([FakeItem(session.config)] * (original_length - len(items)))
3033
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[run]
2+
relative_files=True
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.coverage
2+
rts-coverage.1234
3+
*__pycache__*
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
Decorator, to check that changes in the decorator switch on tests using
3+
decorated functions.
4+
"""
5+
from functools import wraps
6+
from typing import Callable
7+
8+
def decrement(func: Callable[[int], int]) -> Callable[[int], int]:
9+
"""
10+
Decrements the value returned by the decorated function.
11+
"""
12+
@wraps(func)
13+
def _wrapper(num):
14+
return func(num) + 1
15+
16+
return _wrapper
17+
18+
19+
def modify_by(delta: int):
20+
"""
21+
Adds delta to the value returned by the decorated function.
22+
"""
23+
def decorator(func: Callable[[int], int]) -> Callable[[int], int]:
24+
@wraps(func)
25+
def _wrapper(num):
26+
return func(num) + delta
27+
return _wrapper
28+
return decorator
29+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""
2+
Decorator, to check that changes in the decorator switch on tests using
3+
decorated functions.
4+
"""
5+
from functools import wraps
6+
from typing import Callable
7+
8+
def decrement(func: Callable[[int], int]) -> Callable[[int], int]:
9+
"""
10+
Decrements the value returned by the decorated function.
11+
"""
12+
@wraps(func)
13+
def _wrapper(num):
14+
return func(num) - 1
15+
16+
return _wrapper
17+
18+
19+
def modify_by(delta: int):
20+
"""
21+
Adds delta to the value returned by the decorated function.
22+
"""
23+
def decorator(func: Callable[[int], int]) -> Callable[[int], int]:
24+
@wraps(func)
25+
def _wrapper(num):
26+
return func(num) * delta
27+
return _wrapper
28+
return decorator
29+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def one():
2+
return 2
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
2+
class Shop:
3+
4+
def __init__(self,item_price,items,money):
5+
self.item_price = item_price
6+
self.items = items
7+
self.money = money
8+
9+
def buy_item(self):
10+
if self.items > 0:
11+
self.items = self.items - 1
12+
self.money = self.money + self.item_price
13+
14+
def get_items(self):
15+
return self.items
16+
17+
def get_item_price(self):
18+
return self.item_price + 1 - 1
19+
20+
def get_money(self):
21+
return self.money
22+
23+
def calculate_useless_stuff(self):
24+
k = 2
25+
s = "ATGATATCATCGACGATGTAG"
26+
context = {}
27+
for i,c in enumerate(s):
28+
if (i+k >= len(s)):break
29+
substring = s[i:i+k]
30+
if substring not in context:
31+
context[substring] = s[i+k]
32+
else:
33+
context[substring] = context[substring] + s[i+k]
34+
35+
return context
36+
37+
38+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""
2+
Decorated function, to test that changes in the decorator code switch on tests
3+
using the function itself.
4+
"""
5+
6+
from .decorators import decrement, modify_by
7+
8+
@decrement
9+
def decremented_square(num: int) -> int:
10+
"""Square the number and decrement the result."""
11+
return num * num
12+
13+
14+
@modify_by(3)
15+
def modified_double(num: int) -> int:
16+
"""Double the number and and three to the result."""
17+
return 2 * num

0 commit comments

Comments
 (0)