-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add intentions JSON file rendering (for UI docs) (#1)
- Loading branch information
1 parent
46ff6e9
commit 203deca
Showing
20 changed files
with
629 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -105,3 +105,5 @@ venv.bak/ | |
|
||
.idea/ | ||
.DS_Store | ||
|
||
.intentions |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0.0.5 | ||
0.0.6 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
from intentions import ( | ||
case, | ||
describe, | ||
expect, | ||
when, | ||
) | ||
|
||
|
||
@describe(object='Accounts Service', domain='accounts') | ||
class TestAccountsService: | ||
|
||
def test_transfer_money_with_insufficient_balance(self): | ||
with when('Sender account has insufficient balance'): | ||
pass | ||
|
||
with case('Transfer money from one sender to receiver'): | ||
pass | ||
|
||
with expect('No transfers have been made'): | ||
pass | ||
|
||
def test_transfer_money_with_sufficient_balance(self): | ||
with when('Sender account has sufficient balance'): | ||
pass | ||
|
||
with case('Transfer money from one sender to receiver'): | ||
pass | ||
|
||
with expect('Sender account balance decreased on the transfer money amount'): | ||
pass | ||
|
||
|
||
@describe(object='Accounts Service', domain='accounts') | ||
def test_transfer_money_to_non_existing_receiver_account(): | ||
with when('Receiver account does not exist'): | ||
pass | ||
|
||
with case('Transfer money from one sender to receiver'): | ||
pass | ||
|
||
with expect('Receiver account does not exist error is raised'): | ||
pass | ||
|
||
|
||
@describe(object='Investments Service', domain='investments') | ||
class TestInvestmentsService: | ||
|
||
def test_invest_money_into_stocks(self): | ||
with case('Invest money into stocks'): | ||
pass | ||
|
||
with expect('Stock is purchased'): | ||
pass | ||
|
||
def test_invest_money_into_crypto(self): | ||
with case('Invest money into crypto'): | ||
pass | ||
|
||
with expect('Crypto is purchased'): | ||
pass | ||
|
||
|
||
@describe(object='Investments Service', domain='investments') | ||
def test_invest_into_non_existing_stocks(): | ||
with when('Stock to buy does not exist'): | ||
pass | ||
|
||
with case('Invest money into stocks'): | ||
pass | ||
|
||
with expect('Stock does not exist error is raised'): | ||
pass | ||
|
||
|
||
def test_invest_into_non_existing_crypto(): | ||
with when('Crypto to buy does not exist'): | ||
pass | ||
|
||
with case('Invest money into crypto'): | ||
pass | ||
|
||
with expect('Crypto does not exist error is raised'): | ||
pass | ||
|
||
|
||
@describe(object='Investments Service', domain='investments') | ||
def test_sum(): | ||
assert 4 == 2 + 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
from intentions.main import ( | ||
case, | ||
describe, | ||
expect, | ||
when, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
from __future__ import annotations | ||
|
||
import ast | ||
from typing import Optional | ||
|
||
from intentions.render.dto import Describe | ||
|
||
|
||
class AstNodeVisitor(ast.NodeVisitor): | ||
""" | ||
AST node visitor implementation. | ||
""" | ||
|
||
def __init__(self) -> None: | ||
""" | ||
Construct the object. | ||
""" | ||
self.parent_map = {} | ||
self.nodes = [] | ||
|
||
def visit(self, node: ast.AST) -> None: | ||
""" | ||
Visit the node. | ||
It travers the tree in the preorder way and collect parents. Preorder traversal is needed to collect test | ||
functions in the top to down manner with even class's test function be respected. Collecting parents is needed | ||
to have access to class names and description for further rendering. | ||
Arguments: | ||
node (ast.AST): a node to visit, typically the root node. | ||
""" | ||
self.nodes.append(node) | ||
|
||
for child in ast.iter_child_nodes(node): | ||
if child not in self.parent_map: | ||
self.parent_map[child] = node | ||
|
||
self.generic_visit(node) | ||
|
||
def get_parent(self, node: ast.AST) -> Optional[ast.AST]: | ||
return self.parent_map.get(node, None) | ||
|
||
def get_nodes(self) -> list[ast.AST]: | ||
return self.nodes | ||
|
||
def get_describe(self, decorators: [ast.Call]) -> Optional[Describe]: | ||
""" | ||
Get describe context manager description. | ||
Arguments: | ||
decorators (list): list of decorators over a function or class that potentially relate to test cases. | ||
Returns: | ||
An object and domain as `Describe`. | ||
""" | ||
for decorator in decorators: | ||
if not isinstance(decorator, ast.Call): | ||
continue | ||
|
||
if not isinstance(decorator.func, ast.Name): | ||
continue | ||
|
||
if decorator.func.id != 'describe': | ||
continue | ||
|
||
assert decorator.keywords[0].arg == 'object' # noqa: S101 | ||
assert decorator.keywords[1].arg == 'domain' # noqa: S101 | ||
|
||
return Describe( | ||
object=decorator.keywords[0].value.value, | ||
domain=decorator.keywords[1].value.value, | ||
) | ||
|
||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from dataclasses import dataclass | ||
|
||
from intentions.render.enums import Intention | ||
|
||
|
||
@dataclass | ||
class Describe: | ||
object: str # noqa: A003 | ||
domain: str | ||
|
||
|
||
@dataclass | ||
class TestCaseIntention: | ||
|
||
type: Intention # noqa: A003 | ||
code_line: int | ||
description: str | ||
|
||
|
||
@dataclass | ||
class TestCase: | ||
|
||
file_path: str | ||
class_name: str | ||
class_code_line: int | ||
function_name: str | ||
function_code_line: int | ||
intentions: list[TestCaseIntention] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from __future__ import annotations | ||
|
||
from enum import Enum | ||
from json import JSONEncoder | ||
from typing import Union | ||
|
||
|
||
class JsonEncoderWithEnumSupport(JSONEncoder): | ||
|
||
def default(self, obj: Union[Enum, object]) -> object: | ||
if isinstance(obj, Enum): | ||
return obj.value | ||
|
||
return super().default(obj) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from enum import Enum | ||
|
||
|
||
class Intention(Enum): | ||
|
||
WHEN = 'when' | ||
CASE = 'case' | ||
EXPECT = 'expect' |
Oops, something went wrong.