Skip to content
This repository has been archived by the owner on Dec 15, 2023. It is now read-only.

Commit

Permalink
⚡️ Implement xdist for parallel testing (#165)
Browse files Browse the repository at this point in the history
  • Loading branch information
tabaktoni authored Jul 7, 2022
1 parent 9e170e1 commit 127fad7
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 45 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,8 @@ When running tests locally, do it from the project root:

poetry run pytest test/

poetry run pytest -n auto --dist loadscope test/ # parallel testing using n CPU workers

poetry run pytest -s -v test/ # for more verbose output

poetry run pytest test/<TEST_FILE> # for a single file
Expand Down
55 changes: 54 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pylint = "~2.12.2"
web3 = "~5.28.0"
psutil = "~5.9.1"
jsonschema = "~3.2.0"
pytest-xdist = "~2.5.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
Expand Down
19 changes: 12 additions & 7 deletions test/settings.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
"""Constants used in test files."""

import socket

def bind_free_port(host):
"""return assigned free port and test base endpoint"""
sock = socket.socket()
sock.bind(("", 0))
port = str(sock.getsockname()[1])
return port, f"http://{host}:{port}"

HOST = "127.0.0.1"
PORT = "5050"
L1_HOST = "localhost"
L1_PORT = "8545"
PORT, APP_URL = bind_free_port(HOST)

APP_URL = f"http://{HOST}:{PORT}"
GATEWAY_URL = APP_URL
FEEDER_GATEWAY_URL = APP_URL
L1_URL = f"http://{L1_HOST}:{L1_PORT}/"
L1_HOST = "localhost"
L1_PORT, L1_URL = bind_free_port(L1_HOST)
6 changes: 3 additions & 3 deletions test/test_account.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
Test account functionality.
"""
from test.settings import GATEWAY_URL
from test.settings import APP_URL

import json
import requests
Expand Down Expand Up @@ -54,7 +54,7 @@ def deploy_events_contract():

def get_account_balance(address: str) -> int:
"""Get balance (wei) of account with `address` (hex)."""
resp = requests.get(f"{GATEWAY_URL}/account_balance?address={address}")
resp = requests.get(f"{APP_URL}/account_balance?address={address}")
assert resp.status_code == 200
return int(resp.json()["amount"])

Expand Down Expand Up @@ -239,7 +239,7 @@ def test_multicall():
def estimate_fee_local(req_dict: dict):
"""Estimate fee of a given transaction"""
return requests.post(
f"{GATEWAY_URL}/feeder_gateway/estimate_fee",
f"{APP_URL}/feeder_gateway/estimate_fee",
json=req_dict
)

Expand Down
6 changes: 2 additions & 4 deletions test/test_account_predeployed.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
"""Predeployed account tests"""

from test.settings import GATEWAY_URL

import pytest
import requests

from starkware.starknet.core.os.class_hash import compute_class_hash

from starknet_devnet.account import Account
from .util import assert_equal, devnet_in_background
from .support.assertions import assert_valid_schema
from .settings import APP_URL

ACCOUNTS_SEED_DEVNET_ARGS = [
"--accounts",
Expand All @@ -34,6 +32,6 @@ def test_precomputed_contract_hash():
@devnet_in_background(*ACCOUNTS_SEED_DEVNET_ARGS)
def test_predeployed_accounts_predefined_values():
"""Test if --account --seed --initial-balance return exact calculated values"""
response = requests.get(f"{GATEWAY_URL}/predeployed_accounts")
response = requests.get(f"{APP_URL}/predeployed_accounts")
assert response.status_code == 200
assert_valid_schema(response.json(), "predeployed_accounts_fixed_seed.json")
10 changes: 5 additions & 5 deletions test/test_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import pytest

from .util import call, deploy, devnet_in_background, invoke, run_devnet_in_background, terminate_and_wait
from .settings import GATEWAY_URL
from .settings import APP_URL
from .shared import CONTRACT_PATH, ABI_PATH

DUMP_PATH = "dump.pkl"
Expand Down Expand Up @@ -54,17 +54,17 @@ def run_before_and_after_test():
def send_dump_request(dump_path: str=None):
"""Send HTTP request to trigger dumping."""
json_load = { "path": dump_path } if dump_path else None
return requests.post(f"{GATEWAY_URL}/dump", json=json_load)
return requests.post(f"{APP_URL}/dump", json=json_load)

def send_load_request(load_path: str=None):
"""Send HTTP request to trigger loading."""
json_load = { "path": load_path } if load_path else None
return requests.post(f"{GATEWAY_URL}/load", json=json_load)
return requests.post(f"{APP_URL}/load", json=json_load)

def send_error_request():
"""Send HTTP request to trigger error response."""
json_body = { "dummy": "dummy_value" }
return requests.post(f"{GATEWAY_URL}/dump", json=json_body)
return requests.post(f"{APP_URL}/dump", json=json_body)

def assert_dump_present(dump_path: str, sleep_seconds=2):
"""Assert there is a non-empty dump file."""
Expand All @@ -87,7 +87,7 @@ def dump_and_assert(dump_path: str=None):
def assert_not_alive():
"""Assert devnet is not alive."""
try:
requests.get(f"{GATEWAY_URL}/is_alive")
requests.get(f"{APP_URL}/is_alive")
raise RuntimeError("Should have failed before this line.")
except requests.exceptions.ConnectionError:
pass
Expand Down
20 changes: 9 additions & 11 deletions test/test_endpoints.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
Test endpoints directly.
"""

from test.util import load_file_content
from test.settings import GATEWAY_URL

import json
import requests
import pytest

from starknet_devnet.server import app
from .util import devnet_in_background, load_file_content
from .settings import APP_URL

DEPLOY_CONTENT = load_file_content("deploy.json")
INVOKE_CONTENT = load_file_content("invoke.json")
Expand Down Expand Up @@ -120,53 +118,53 @@ def test_call_with_complete_request_data():
def send_transaction_with_requests(req_dict: dict):
"""Sends the dict in a POST request and returns the response data."""
return requests.post(
f"{GATEWAY_URL}/gateway/add_transaction",
f"{APP_URL}/gateway/add_transaction",
json=json.dumps(req_dict)
)

def send_call_with_requests(req_dict: dict):
"""Sends the call dict in a POST request and returns the response data."""
return requests.post(
f"{GATEWAY_URL}/feeder_gateway/call_contract",
f"{APP_URL}/feeder_gateway/call_contract",
json=json.dumps(req_dict)
)

def get_block_number(req_dict: dict):
"""Get block number from request dict"""
block_number = req_dict["blockNumber"]
return requests.get(
f"{GATEWAY_URL}/feeder_gateway/get_block?blockNumber={block_number}"
f"{APP_URL}/feeder_gateway/get_block?blockNumber={block_number}"
)

def get_transaction_trace(transaction_hash:str):
"""Get transaction trace from request dict"""
# transactionHash
return requests.get(
f"{GATEWAY_URL}/feeder_gateway/get_transaction_trace?transactionHash={transaction_hash}"
f"{APP_URL}/feeder_gateway/get_transaction_trace?transactionHash={transaction_hash}"
)

def get_full_contract(contract_adress):
"""Get full contract class of a contract at a specific address"""
return requests.get(
f"{GATEWAY_URL}/feeder_gateway/get_full_contract?contractAddress={contract_adress}"
f"{APP_URL}/feeder_gateway/get_full_contract?contractAddress={contract_adress}"
)

def get_class_by_hash(class_hash: str):
"""Get contract class by class hash"""
return requests.get(
f"{GATEWAY_URL}/feeder_gateway/get_class_by_hash?classHash={class_hash}"
f"{APP_URL}/feeder_gateway/get_class_by_hash?classHash={class_hash}"
)

def get_class_hash_at(contract_address: str):
"""Get class hash of a contract at the provided address"""
return requests.get(
f"{GATEWAY_URL}/feeder_gateway/get_class_hash_at?contractAddress={contract_address}"
f"{APP_URL}/feeder_gateway/get_class_hash_at?contractAddress={contract_address}"
)

def get_state_update(block_hash, block_number):
"""Get state update"""
return requests.get(
f"{GATEWAY_URL}/feeder_gateway/get_state_update?blockHash={block_hash}&blockNumber={block_number}"
f"{APP_URL}/feeder_gateway/get_state_update?blockHash={block_hash}&blockNumber={block_number}"
)

@devnet_in_background()
Expand Down
10 changes: 5 additions & 5 deletions test/test_postman.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import subprocess

from test.web3_util import web3_call, web3_deploy, web3_transact
from test.settings import L1_HOST, L1_PORT, L1_URL, GATEWAY_URL
from test.settings import APP_URL, L1_HOST, L1_PORT, L1_URL
from test.util import call, deploy, devnet_in_background, ensure_server_alive, invoke, load_file_content, terminate_and_wait

import psutil
Expand Down Expand Up @@ -49,7 +49,7 @@ def run_before_and_after_test():
def flush():
"""Flushes the postman messages. Returns response data"""
res = requests.post(
f"{GATEWAY_URL}/postman/flush"
f"{APP_URL}/postman/flush"
)

return res.json()
Expand Down Expand Up @@ -90,7 +90,7 @@ def init_messaging_contract():
"networkUrl": L1_URL
}
resp = requests.post(
f"{GATEWAY_URL}/postman/load_l1_messaging_contract",
f"{APP_URL}/postman/load_l1_messaging_contract",
json=deploy_messaging_contract_request
)
return json.loads(resp.text)
Expand Down Expand Up @@ -120,7 +120,7 @@ def load_messaging_contract(starknet_messaging_contract_address):
}

resp = requests.post(
f"{GATEWAY_URL}/postman/load_l1_messaging_contract",
f"{APP_URL}/postman/load_l1_messaging_contract",
json=load_messaging_contract_request
)

Expand Down Expand Up @@ -276,7 +276,7 @@ def test_postman():
def load_l1_messaging_contract(req_dict: dict):
"""Load L1 messaging contract"""
return requests.post(
f"{GATEWAY_URL}/postman/load_l1_messaging_contract",
f"{APP_URL}/postman/load_l1_messaging_contract",
json=(req_dict)
)

Expand Down
4 changes: 2 additions & 2 deletions test/test_restart.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pytest
import requests

from .settings import APP_URL, FEEDER_GATEWAY_URL
from .settings import APP_URL
from .util import devnet_in_background, deploy, assert_transaction_not_received, assert_tx_status, call, invoke
from .shared import CONTRACT_PATH, ABI_PATH

Expand All @@ -15,7 +15,7 @@ def restart():

def get_state_update():
"""Get state update"""
res = requests.get(f"{FEEDER_GATEWAY_URL}/feeder_gateway/get_state_update")
res = requests.get(f"{APP_URL}/feeder_gateway/get_state_update")
return res.json()


Expand Down
4 changes: 2 additions & 2 deletions test/test_state_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .util import (
deploy, invoke, load_contract_class, devnet_in_background, get_block, assert_equal
)
from .settings import FEEDER_GATEWAY_URL
from .settings import APP_URL
from .shared import STORAGE_CONTRACT_PATH, STORAGE_ABI_PATH

STORAGE_KEY = hex(get_selector_from_name("storage"))
Expand All @@ -24,7 +24,7 @@ def get_state_update_response(block_hash=None, block_number=None):
}

res = requests.get(
f"{FEEDER_GATEWAY_URL}/feeder_gateway/get_state_update",
f"{APP_URL}/feeder_gateway/get_state_update",
params=params
)

Expand Down
4 changes: 2 additions & 2 deletions test/test_transaction_trace.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import requests

from .util import deploy, invoke, load_json_from_path, devnet_in_background
from .settings import FEEDER_GATEWAY_URL
from .settings import APP_URL
from .shared import ABI_PATH, CONTRACT_PATH, SIGNATURE, NONEXISTENT_TX_HASH

def get_transaction_trace_response(tx_hash=None):
Expand All @@ -16,7 +16,7 @@ def get_transaction_trace_response(tx_hash=None):
}

res = requests.get(
f"{FEEDER_GATEWAY_URL}/feeder_gateway/get_transaction_trace",
f"{APP_URL}/feeder_gateway/get_transaction_trace",
params=params
)

Expand Down
Loading

0 comments on commit 127fad7

Please sign in to comment.