diff --git a/examples/generators/production_python_smart_contract_python/.algokit.toml b/examples/generators/production_python_smart_contract_python/.algokit.toml index 31a2642..6ebb852 100644 --- a/examples/generators/production_python_smart_contract_python/.algokit.toml +++ b/examples/generators/production_python_smart_contract_python/.algokit.toml @@ -34,7 +34,7 @@ audit = { commands = [ ], description = 'Audit with pip-audit' } lint = { commands = [ 'poetry run black --check .', - 'poetry run ruff .', + 'poetry run ruff check .', 'poetry run mypy', ], description = 'Perform linting' } audit-teal = { commands = [ diff --git a/examples/generators/production_python_smart_contract_python/.gitignore b/examples/generators/production_python_smart_contract_python/.gitignore index e5f0b9e..a858d63 100644 --- a/examples/generators/production_python_smart_contract_python/.gitignore +++ b/examples/generators/production_python_smart_contract_python/.gitignore @@ -176,5 +176,5 @@ node_modules # AlgoKit debug_traces/ - .algokit/static-analysis/tealer/ +.algokit/sources diff --git a/examples/generators/production_python_smart_contract_python/.pre-commit-config.yaml b/examples/generators/production_python_smart_contract_python/.pre-commit-config.yaml index 9099d0a..69d8fdf 100644 --- a/examples/generators/production_python_smart_contract_python/.pre-commit-config.yaml +++ b/examples/generators/production_python_smart_contract_python/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: entry: poetry run ruff language: system types: [ python ] - args: [ --fix ] + args: [ "check", "--fix" ] require_serial: false additional_dependencies: [ ] minimum_pre_commit_version: '0' diff --git a/examples/generators/production_python_smart_contract_python/README.md b/examples/generators/production_python_smart_contract_python/README.md index 13e98b8..3ac8154 100644 --- a/examples/generators/production_python_smart_contract_python/README.md +++ b/examples/generators/production_python_smart_contract_python/README.md @@ -102,7 +102,9 @@ For pull requests and pushes to `main` branch against this repository the follow - Code formatting is checked using [Black](https://github.com/psf/black) - Linting is checked using [Ruff](https://github.com/charliermarsh/ruff) - Types are checked using [mypy](https://mypy-lang.org/) - - Python tests are executed using [pytest](https://docs.pytest.org/) +- The base framework for testing is [pytest](https://docs.pytest.org/), and the project includes two separate kinds of tests: +- - `Algorand Python` smart contract unit tests, that are run using [`algorand-python-testing`](https://pypi.org/project/algorand-python-testing/), which are executed in a Python intepreter emulating major AVM behaviour +- - Python `ApplicationClient` tests that are run against `algokit localnet` and test the behaviour in a real network enviornment - Smart contract artifacts are built - Smart contract artifacts are checked for [output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md) - Smart contract is deployed to a AlgoKit LocalNet instance diff --git a/examples/generators/production_python_smart_contract_python/pyproject.toml b/examples/generators/production_python_smart_contract_python/pyproject.toml index 68eb615..c7ee2d8 100644 --- a/examples/generators/production_python_smart_contract_python/pyproject.toml +++ b/examples/generators/production_python_smart_contract_python/pyproject.toml @@ -7,9 +7,10 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.2.0" +algokit-utils = "^2.3.0" python-dotenv = "^1.0.0" algorand-python = "^1.0.0" +algorand-python-testing = {git = "https://github.com/algorandfoundation/puya.git", rev = "fix/algopy_testing_refinements", subdirectory = "algopy_testing"} [tool.poetry.group.dev.dependencies] algokit-client-generator = "^1.1.3" diff --git a/examples/generators/production_python_smart_contract_python/tests/hello_world_client_test.py b/examples/generators/production_python_smart_contract_python/tests/hello_world_client_test.py new file mode 100644 index 0000000..bb13a43 --- /dev/null +++ b/examples/generators/production_python_smart_contract_python/tests/hello_world_client_test.py @@ -0,0 +1,48 @@ +import algokit_utils +import pytest +from algokit_utils import get_localnet_default_account +from algokit_utils.config import config +from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient + +from smart_contracts.artifacts.hello_world.client import HelloWorldClient + + +@pytest.fixture(scope="session") +def hello_world_client( + algod_client: AlgodClient, indexer_client: IndexerClient +) -> HelloWorldClient: + config.configure( + debug=True, + # trace_all=True, + ) + + client = HelloWorldClient( + algod_client, + creator=get_localnet_default_account(algod_client), + indexer_client=indexer_client, + ) + + client.deploy( + on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, + on_update=algokit_utils.OnUpdate.AppendApp, + ) + return client + + +def test_says_hello(hello_world_client: HelloWorldClient) -> None: + result = hello_world_client.hello(name="World") + + assert result.return_value == "Hello, World" + + +def test_simulate_says_hello_with_correct_budget_consumed( + hello_world_client: HelloWorldClient, algod_client: AlgodClient +) -> None: + result = ( + hello_world_client.compose().hello(name="World").hello(name="Jane").simulate() + ) + + assert result.abi_results[0].return_value == "Hello, World" + assert result.abi_results[1].return_value == "Hello, Jane" + assert result.simulate_response["txn-groups"][0]["app-budget-consumed"] < 100 diff --git a/examples/generators/production_python_smart_contract_python/tests/hello_world_test.py b/examples/generators/production_python_smart_contract_python/tests/hello_world_test.py index bb13a43..8e2afc1 100644 --- a/examples/generators/production_python_smart_contract_python/tests/hello_world_test.py +++ b/examples/generators/production_python_smart_contract_python/tests/hello_world_test.py @@ -1,48 +1,25 @@ -import algokit_utils -import pytest -from algokit_utils import get_localnet_default_account -from algokit_utils.config import config -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -from smart_contracts.artifacts.hello_world.client import HelloWorldClient - +from collections.abc import Generator -@pytest.fixture(scope="session") -def hello_world_client( - algod_client: AlgodClient, indexer_client: IndexerClient -) -> HelloWorldClient: - config.configure( - debug=True, - # trace_all=True, - ) - - client = HelloWorldClient( - algod_client, - creator=get_localnet_default_account(algod_client), - indexer_client=indexer_client, - ) +import pytest +from algopy_testing import AlgopyTestContext, algopy_testing_context - client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - return client +from smart_contracts.hello_world.contract import HelloWorld -def test_says_hello(hello_world_client: HelloWorldClient) -> None: - result = hello_world_client.hello(name="World") +@pytest.fixture() +def context() -> Generator[AlgopyTestContext, None, None]: + with algopy_testing_context() as ctx: + yield ctx + ctx.reset() - assert result.return_value == "Hello, World" +def test_hello(context: AlgopyTestContext) -> None: + # Arrange + dummy_input = context.any_string() + contract = HelloWorld() -def test_simulate_says_hello_with_correct_budget_consumed( - hello_world_client: HelloWorldClient, algod_client: AlgodClient -) -> None: - result = ( - hello_world_client.compose().hello(name="World").hello(name="Jane").simulate() - ) + # Act + output = contract.hello(dummy_input) - assert result.abi_results[0].return_value == "Hello, World" - assert result.abi_results[1].return_value == "Hello, Jane" - assert result.simulate_response["txn-groups"][0]["app-budget-consumed"] < 100 + # Assert + assert output == f"Hello, {dummy_input}" diff --git a/examples/generators/production_python_smart_contract_typescript/.algokit.toml b/examples/generators/production_python_smart_contract_typescript/.algokit.toml index 612f1b2..3cb1106 100644 --- a/examples/generators/production_python_smart_contract_typescript/.algokit.toml +++ b/examples/generators/production_python_smart_contract_typescript/.algokit.toml @@ -34,7 +34,7 @@ audit = { commands = [ ], description = 'Audit with pip-audit' } lint = { commands = [ 'poetry run black --check .', - 'poetry run ruff .', + 'poetry run ruff check .', 'poetry run mypy', ], description = 'Perform linting' } audit-teal = { commands = [ diff --git a/examples/generators/production_python_smart_contract_typescript/.gitignore b/examples/generators/production_python_smart_contract_typescript/.gitignore index e5f0b9e..a858d63 100644 --- a/examples/generators/production_python_smart_contract_typescript/.gitignore +++ b/examples/generators/production_python_smart_contract_typescript/.gitignore @@ -176,5 +176,5 @@ node_modules # AlgoKit debug_traces/ - .algokit/static-analysis/tealer/ +.algokit/sources diff --git a/examples/generators/production_python_smart_contract_typescript/.pre-commit-config.yaml b/examples/generators/production_python_smart_contract_typescript/.pre-commit-config.yaml index 9099d0a..69d8fdf 100644 --- a/examples/generators/production_python_smart_contract_typescript/.pre-commit-config.yaml +++ b/examples/generators/production_python_smart_contract_typescript/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: entry: poetry run ruff language: system types: [ python ] - args: [ --fix ] + args: [ "check", "--fix" ] require_serial: false additional_dependencies: [ ] minimum_pre_commit_version: '0' diff --git a/examples/generators/production_python_smart_contract_typescript/README.md b/examples/generators/production_python_smart_contract_typescript/README.md index 533588e..f1994e5 100644 --- a/examples/generators/production_python_smart_contract_typescript/README.md +++ b/examples/generators/production_python_smart_contract_typescript/README.md @@ -102,6 +102,7 @@ For pull requests and pushes to `main` branch against this repository the follow - Code formatting is checked using [Black](https://github.com/psf/black) - Linting is checked using [Ruff](https://github.com/charliermarsh/ruff) - Types are checked using [mypy](https://mypy-lang.org/) + - Typescript `ApplicationClient` tests against `algokit localnet` are executed using [jest](https://jestjs.io/) - Smart contract artifacts are built - Smart contract artifacts are checked for [output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md) - Smart contract is deployed to a AlgoKit LocalNet instance diff --git a/examples/generators/production_python_smart_contract_typescript/pyproject.toml b/examples/generators/production_python_smart_contract_typescript/pyproject.toml index 41671dd..d33d978 100644 --- a/examples/generators/production_python_smart_contract_typescript/pyproject.toml +++ b/examples/generators/production_python_smart_contract_typescript/pyproject.toml @@ -7,9 +7,10 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.2.0" +algokit-utils = "^2.3.0" python-dotenv = "^1.0.0" algorand-python = "^1.0.0" +algorand-python-testing = {git = "https://github.com/algorandfoundation/puya.git", rev = "fix/algopy_testing_refinements", subdirectory = "algopy_testing"} [tool.poetry.group.dev.dependencies] black = {extras = ["d"], version = "*"} diff --git a/examples/generators/starter_python_smart_contract_python/.gitignore b/examples/generators/starter_python_smart_contract_python/.gitignore index e5f0b9e..a858d63 100644 --- a/examples/generators/starter_python_smart_contract_python/.gitignore +++ b/examples/generators/starter_python_smart_contract_python/.gitignore @@ -176,5 +176,5 @@ node_modules # AlgoKit debug_traces/ - .algokit/static-analysis/tealer/ +.algokit/sources diff --git a/examples/generators/starter_python_smart_contract_python/pyproject.toml b/examples/generators/starter_python_smart_contract_python/pyproject.toml index b49fc6b..00c7488 100644 --- a/examples/generators/starter_python_smart_contract_python/pyproject.toml +++ b/examples/generators/starter_python_smart_contract_python/pyproject.toml @@ -7,9 +7,10 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.2.0" +algokit-utils = "^2.3.0" python-dotenv = "^1.0.0" algorand-python = "^1.0.0" +algorand-python-testing = {git = "https://github.com/algorandfoundation/puya.git", rev = "fix/algopy_testing_refinements", subdirectory = "algopy_testing"} [tool.poetry.group.dev.dependencies] algokit-client-generator = "^1.1.3" diff --git a/examples/generators/starter_python_smart_contract_typescript/.gitignore b/examples/generators/starter_python_smart_contract_typescript/.gitignore index e5f0b9e..a858d63 100644 --- a/examples/generators/starter_python_smart_contract_typescript/.gitignore +++ b/examples/generators/starter_python_smart_contract_typescript/.gitignore @@ -176,5 +176,5 @@ node_modules # AlgoKit debug_traces/ - .algokit/static-analysis/tealer/ +.algokit/sources diff --git a/examples/generators/starter_python_smart_contract_typescript/pyproject.toml b/examples/generators/starter_python_smart_contract_typescript/pyproject.toml index c1cb3f6..8aefa5d 100644 --- a/examples/generators/starter_python_smart_contract_typescript/pyproject.toml +++ b/examples/generators/starter_python_smart_contract_typescript/pyproject.toml @@ -7,9 +7,10 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.2.0" +algokit-utils = "^2.3.0" python-dotenv = "^1.0.0" algorand-python = "^1.0.0" +algorand-python-testing = {git = "https://github.com/algorandfoundation/puya.git", rev = "fix/algopy_testing_refinements", subdirectory = "algopy_testing"} [tool.poetry.group.dev.dependencies] puyapy = "*" diff --git a/examples/production_python/.algokit.toml b/examples/production_python/.algokit.toml index 17aa09d..58d90ea 100644 --- a/examples/production_python/.algokit.toml +++ b/examples/production_python/.algokit.toml @@ -34,7 +34,7 @@ audit = { commands = [ ], description = 'Audit with pip-audit' } lint = { commands = [ 'poetry run black --check .', - 'poetry run ruff .', + 'poetry run ruff check .', 'poetry run mypy', ], description = 'Perform linting' } audit-teal = { commands = [ diff --git a/examples/production_python/.gitignore b/examples/production_python/.gitignore index e5f0b9e..a858d63 100644 --- a/examples/production_python/.gitignore +++ b/examples/production_python/.gitignore @@ -176,5 +176,5 @@ node_modules # AlgoKit debug_traces/ - .algokit/static-analysis/tealer/ +.algokit/sources diff --git a/examples/production_python/.pre-commit-config.yaml b/examples/production_python/.pre-commit-config.yaml index 9099d0a..69d8fdf 100644 --- a/examples/production_python/.pre-commit-config.yaml +++ b/examples/production_python/.pre-commit-config.yaml @@ -18,7 +18,7 @@ repos: entry: poetry run ruff language: system types: [ python ] - args: [ --fix ] + args: [ "check", "--fix" ] require_serial: false additional_dependencies: [ ] minimum_pre_commit_version: '0' diff --git a/examples/production_python/README.md b/examples/production_python/README.md index e728d55..061dbf0 100644 --- a/examples/production_python/README.md +++ b/examples/production_python/README.md @@ -102,7 +102,9 @@ For pull requests and pushes to `main` branch against this repository the follow - Code formatting is checked using [Black](https://github.com/psf/black) - Linting is checked using [Ruff](https://github.com/charliermarsh/ruff) - Types are checked using [mypy](https://mypy-lang.org/) - - Python tests are executed using [pytest](https://docs.pytest.org/) +- The base framework for testing is [pytest](https://docs.pytest.org/), and the project includes two separate kinds of tests: +- - `Algorand Python` smart contract unit tests, that are run using [`algorand-python-testing`](https://pypi.org/project/algorand-python-testing/), which are executed in a Python intepreter emulating major AVM behaviour +- - Python `ApplicationClient` tests that are run against `algokit localnet` and test the behaviour in a real network enviornment - Smart contract artifacts are built - Smart contract artifacts are checked for [output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md) - Smart contract is deployed to a AlgoKit LocalNet instance diff --git a/examples/production_python/pyproject.toml b/examples/production_python/pyproject.toml index c8246c7..27e03d4 100644 --- a/examples/production_python/pyproject.toml +++ b/examples/production_python/pyproject.toml @@ -7,9 +7,10 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.2.0" +algokit-utils = "^2.3.0" python-dotenv = "^1.0.0" algorand-python = "^1.0.0" +algorand-python-testing = {git = "https://github.com/algorandfoundation/puya.git", rev = "fix/algopy_testing_refinements", subdirectory = "algopy_testing"} [tool.poetry.group.dev.dependencies] algokit-client-generator = "^1.1.3" diff --git a/examples/production_python/tests/hello_world_client_test.py b/examples/production_python/tests/hello_world_client_test.py new file mode 100644 index 0000000..bb13a43 --- /dev/null +++ b/examples/production_python/tests/hello_world_client_test.py @@ -0,0 +1,48 @@ +import algokit_utils +import pytest +from algokit_utils import get_localnet_default_account +from algokit_utils.config import config +from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient + +from smart_contracts.artifacts.hello_world.client import HelloWorldClient + + +@pytest.fixture(scope="session") +def hello_world_client( + algod_client: AlgodClient, indexer_client: IndexerClient +) -> HelloWorldClient: + config.configure( + debug=True, + # trace_all=True, + ) + + client = HelloWorldClient( + algod_client, + creator=get_localnet_default_account(algod_client), + indexer_client=indexer_client, + ) + + client.deploy( + on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, + on_update=algokit_utils.OnUpdate.AppendApp, + ) + return client + + +def test_says_hello(hello_world_client: HelloWorldClient) -> None: + result = hello_world_client.hello(name="World") + + assert result.return_value == "Hello, World" + + +def test_simulate_says_hello_with_correct_budget_consumed( + hello_world_client: HelloWorldClient, algod_client: AlgodClient +) -> None: + result = ( + hello_world_client.compose().hello(name="World").hello(name="Jane").simulate() + ) + + assert result.abi_results[0].return_value == "Hello, World" + assert result.abi_results[1].return_value == "Hello, Jane" + assert result.simulate_response["txn-groups"][0]["app-budget-consumed"] < 100 diff --git a/examples/production_python/tests/hello_world_test.py b/examples/production_python/tests/hello_world_test.py index bb13a43..8e2afc1 100644 --- a/examples/production_python/tests/hello_world_test.py +++ b/examples/production_python/tests/hello_world_test.py @@ -1,48 +1,25 @@ -import algokit_utils -import pytest -from algokit_utils import get_localnet_default_account -from algokit_utils.config import config -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -from smart_contracts.artifacts.hello_world.client import HelloWorldClient - +from collections.abc import Generator -@pytest.fixture(scope="session") -def hello_world_client( - algod_client: AlgodClient, indexer_client: IndexerClient -) -> HelloWorldClient: - config.configure( - debug=True, - # trace_all=True, - ) - - client = HelloWorldClient( - algod_client, - creator=get_localnet_default_account(algod_client), - indexer_client=indexer_client, - ) +import pytest +from algopy_testing import AlgopyTestContext, algopy_testing_context - client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - return client +from smart_contracts.hello_world.contract import HelloWorld -def test_says_hello(hello_world_client: HelloWorldClient) -> None: - result = hello_world_client.hello(name="World") +@pytest.fixture() +def context() -> Generator[AlgopyTestContext, None, None]: + with algopy_testing_context() as ctx: + yield ctx + ctx.reset() - assert result.return_value == "Hello, World" +def test_hello(context: AlgopyTestContext) -> None: + # Arrange + dummy_input = context.any_string() + contract = HelloWorld() -def test_simulate_says_hello_with_correct_budget_consumed( - hello_world_client: HelloWorldClient, algod_client: AlgodClient -) -> None: - result = ( - hello_world_client.compose().hello(name="World").hello(name="Jane").simulate() - ) + # Act + output = contract.hello(dummy_input) - assert result.abi_results[0].return_value == "Hello, World" - assert result.abi_results[1].return_value == "Hello, Jane" - assert result.simulate_response["txn-groups"][0]["app-budget-consumed"] < 100 + # Assert + assert output == f"Hello, {dummy_input}" diff --git a/examples/starter_python/.gitignore b/examples/starter_python/.gitignore index e5f0b9e..a858d63 100644 --- a/examples/starter_python/.gitignore +++ b/examples/starter_python/.gitignore @@ -176,5 +176,5 @@ node_modules # AlgoKit debug_traces/ - .algokit/static-analysis/tealer/ +.algokit/sources diff --git a/examples/starter_python/pyproject.toml b/examples/starter_python/pyproject.toml index 9fb8217..8016d41 100644 --- a/examples/starter_python/pyproject.toml +++ b/examples/starter_python/pyproject.toml @@ -7,9 +7,10 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.2.0" +algokit-utils = "^2.3.0" python-dotenv = "^1.0.0" algorand-python = "^1.0.0" +algorand-python-testing = {git = "https://github.com/algorandfoundation/puya.git", rev = "fix/algopy_testing_refinements", subdirectory = "algopy_testing"} [tool.poetry.group.dev.dependencies] algokit-client-generator = "^1.1.3" diff --git a/template_content/.algokit.toml.jinja b/template_content/.algokit.toml.jinja index c6b1d4d..9ecaf47 100644 --- a/template_content/.algokit.toml.jinja +++ b/template_content/.algokit.toml.jinja @@ -51,7 +51,7 @@ lint = { commands = [ 'poetry run black --check .', {%- endif %} {%- if python_linter == 'ruff' %} - 'poetry run ruff .', + 'poetry run ruff check .', {%- elif python_linter == 'flake8' %} 'poetry run flake8 .', {%- endif %} diff --git a/template_content/.gitignore.jinja b/template_content/.gitignore.jinja index e5f0b9e..a858d63 100644 --- a/template_content/.gitignore.jinja +++ b/template_content/.gitignore.jinja @@ -176,5 +176,5 @@ node_modules # AlgoKit debug_traces/ - .algokit/static-analysis/tealer/ +.algokit/sources diff --git a/template_content/README.md.jinja b/template_content/README.md.jinja index 8ce113d..ffc4794 100644 --- a/template_content/README.md.jinja +++ b/template_content/README.md.jinja @@ -126,7 +126,12 @@ For pull requests and pushes to `main` branch against this repository the follow - Types are checked using [mypy](https://mypy-lang.org/) {%- endif %} {%- if use_python_pytest %} - - Python tests are executed using [pytest](https://docs.pytest.org/) +- The base framework for testing is [pytest](https://docs.pytest.org/), and the project includes two separate kinds of tests: +- - `Algorand Python` smart contract unit tests, that are run using [`algorand-python-testing`](https://pypi.org/project/algorand-python-testing/), which are executed in a Python intepreter emulating major AVM behaviour +- - Python `ApplicationClient` tests that are run against `algokit localnet` and test the behaviour in a real network enviornment +{%- endif %} +{%- if use_typescript_jest %} + - Typescript `ApplicationClient` tests against `algokit localnet` are executed using [jest](https://jestjs.io/) {%- endif %} - Smart contract artifacts are built - Smart contract artifacts are checked for [output stability](https://github.com/algorandfoundation/algokit-cli/blob/main/docs/articles/output_stability.md) diff --git a/template_content/pyproject.toml.jinja b/template_content/pyproject.toml.jinja index 8235fba..9c6a9c7 100644 --- a/template_content/pyproject.toml.jinja +++ b/template_content/pyproject.toml.jinja @@ -7,9 +7,10 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" -algokit-utils = "^2.2.0" +algokit-utils = "^2.3.0" python-dotenv = "^1.0.0" algorand-python = "^1.0.0" +algorand-python-testing = {git = "https://github.com/algorandfoundation/puya.git", rev = "fix/algopy_testing_refinements", subdirectory = "algopy_testing"} [tool.poetry.group.dev.dependencies] {% if deployment_language == 'python' -%} diff --git a/template_content/{% if use_pre_commit %}.pre-commit-config.yaml{% endif %}.jinja b/template_content/{% if use_pre_commit %}.pre-commit-config.yaml{% endif %}.jinja index 4a06c33..47de4b7 100644 --- a/template_content/{% if use_pre_commit %}.pre-commit-config.yaml{% endif %}.jinja +++ b/template_content/{% if use_pre_commit %}.pre-commit-config.yaml{% endif %}.jinja @@ -18,7 +18,7 @@ repos: entry: poetry run ruff language: system types: [ python ] - args: [ --fix ] + args: [ "check", "--fix" ] require_serial: false additional_dependencies: [ ] minimum_pre_commit_version: '0' diff --git a/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_client_test.py{% endif %}.jinja b/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_client_test.py{% endif %}.jinja new file mode 100644 index 0000000..bbd585a --- /dev/null +++ b/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_client_test.py{% endif %}.jinja @@ -0,0 +1,48 @@ +import algokit_utils +import pytest +from algokit_utils import get_localnet_default_account +from algokit_utils.config import config +from algosdk.v2client.algod import AlgodClient +from algosdk.v2client.indexer import IndexerClient + +from smart_contracts.artifacts.{{ contract_name }}.client import {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client + + +@pytest.fixture(scope="session") +def {{ contract_name }}_client( + algod_client: AlgodClient, indexer_client: IndexerClient +) -> {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client: + config.configure( + debug=True, + # trace_all=True, + ) + + client = {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client( + algod_client, + creator=get_localnet_default_account(algod_client), + indexer_client=indexer_client, + ) + + client.deploy( + on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, + on_update=algokit_utils.OnUpdate.AppendApp, + ) + return client + + +def test_says_hello({{ contract_name }}_client: {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client) -> None: + result = {{ contract_name }}_client.hello(name="World") + + assert result.return_value == "Hello, World" + + +def test_simulate_says_hello_with_correct_budget_consumed( + {{ contract_name }}_client: {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client, algod_client: AlgodClient +) -> None: + result = ( + {{ contract_name }}_client.compose().hello(name="World").hello(name="Jane").simulate() + ) + + assert result.abi_results[0].return_value == "Hello, World" + assert result.abi_results[1].return_value == "Hello, Jane" + assert result.simulate_response["txn-groups"][0]["app-budget-consumed"] < 100 diff --git a/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_test.py{% endif %}.jinja b/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_test.py{% endif %}.jinja index bbd585a..c02858b 100644 --- a/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_test.py{% endif %}.jinja +++ b/template_content/{% if use_python_pytest %}tests{% endif %}/{% if use_python_pytest %}{{ contract_name }}_test.py{% endif %}.jinja @@ -1,48 +1,25 @@ -import algokit_utils -import pytest -from algokit_utils import get_localnet_default_account -from algokit_utils.config import config -from algosdk.v2client.algod import AlgodClient -from algosdk.v2client.indexer import IndexerClient - -from smart_contracts.artifacts.{{ contract_name }}.client import {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client - +from collections.abc import Generator -@pytest.fixture(scope="session") -def {{ contract_name }}_client( - algod_client: AlgodClient, indexer_client: IndexerClient -) -> {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client: - config.configure( - debug=True, - # trace_all=True, - ) - - client = {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client( - algod_client, - creator=get_localnet_default_account(algod_client), - indexer_client=indexer_client, - ) +import pytest +from algopy_testing import AlgopyTestContext, algopy_testing_context - client.deploy( - on_schema_break=algokit_utils.OnSchemaBreak.AppendApp, - on_update=algokit_utils.OnUpdate.AppendApp, - ) - return client +from smart_contracts.{{ contract_name }}.contract import {{ contract_name.split('_')|map('capitalize')|join }} -def test_says_hello({{ contract_name }}_client: {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client) -> None: - result = {{ contract_name }}_client.hello(name="World") +@pytest.fixture() +def context() -> Generator[AlgopyTestContext, None, None]: + with algopy_testing_context() as ctx: + yield ctx + ctx.reset() - assert result.return_value == "Hello, World" +def test_hello(context: AlgopyTestContext) -> None: + # Arrange + dummy_input = context.any_string() + contract = {{ contract_name.split('_')|map('capitalize')|join }}() -def test_simulate_says_hello_with_correct_budget_consumed( - {{ contract_name }}_client: {% include pathjoin('includes', 'contract_name_pascal.jinja') %}Client, algod_client: AlgodClient -) -> None: - result = ( - {{ contract_name }}_client.compose().hello(name="World").hello(name="Jane").simulate() - ) + # Act + output = contract.hello(dummy_input) - assert result.abi_results[0].return_value == "Hello, World" - assert result.abi_results[1].return_value == "Hello, Jane" - assert result.simulate_response["txn-groups"][0]["app-budget-consumed"] < 100 + # Assert + assert output == f"Hello, {dummy_input}"