Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,29 @@ jeff.py
*/venv/
data
venv/

# Testing
.pytest_cache/
.coverage
htmlcov/
coverage.xml
.tox/

# Claude Code
.claude/*

# Virtual environments
.venv/
env/
ENV/

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db
469 changes: 469 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

92 changes: 92 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
[tool.poetry]
name = "btcpay-python"
version = "1.3.0"
description = "Accept bitcoin with BTCPay"
authors = ["BTCPay Server Contributors"]
license = "MIT"
readme = "README.md"
homepage = "https://github.com/btcpayserver/btcpay-python"
repository = "https://github.com/btcpayserver/btcpay-python"
keywords = ["bitcoin", "payments", "crypto"]
classifiers = [
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3 :: Only",
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Office/Business :: Financial"
]
packages = [{include = "btcpay"}]

[tool.poetry.dependencies]
python = "^3.8"
requests = "*"
ecdsa = "*"

[tool.poetry.group.test.dependencies]
pytest = "^7.0.0"
pytest-cov = "^4.0.0"
pytest-mock = "^3.10.0"

[tool.poetry.scripts]

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"--strict-markers",
"--strict-config",
"--verbose",
"--cov=btcpay",
"--cov-report=term-missing",
"--cov-report=html:htmlcov",
"--cov-report=xml:coverage.xml",
"--cov-fail-under=80"
]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Slow running tests"
]

[tool.coverage.run]
source = ["btcpay"]
omit = [
"*/tests/*",
"*/test_*",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
"setup.py"
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod"
]
show_missing = true
precision = 2

[tool.coverage.html]
directory = "htmlcov"

[tool.coverage.xml]
output = "coverage.xml"
Empty file added tests/__init__.py
Empty file.
68 changes: 68 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import os
import tempfile
import pytest
from unittest.mock import Mock, MagicMock


@pytest.fixture
def temp_dir():
"""Create a temporary directory for tests."""
with tempfile.TemporaryDirectory() as tmpdir:
yield tmpdir


@pytest.fixture
def mock_config():
"""Provide a mock configuration object."""
config = {
'api_url': 'https://testnet.demo.btcpayserver.org',
'pem': 'test_private_key',
'tokens': {'merchant': 'test_token'}
}
return config


@pytest.fixture
def mock_requests():
"""Provide a mock requests object."""
mock = Mock()
mock.post.return_value.json.return_value = {'status': 'success'}
mock.post.return_value.status_code = 200
mock.get.return_value.json.return_value = {'status': 'success'}
mock.get.return_value.status_code = 200
return mock


@pytest.fixture
def sample_invoice_data():
"""Provide sample invoice data for testing."""
return {
'price': 10.0,
'currency': 'USD',
'orderId': 'test_order_123',
'notificationURL': 'https://example.com/webhook'
}


@pytest.fixture
def mock_btcpay_client():
"""Provide a mock BTCPay client instance."""
client = MagicMock()
client.create_invoice.return_value = {
'id': 'test_invoice_id',
'url': 'https://testnet.demo.btcpayserver.org/invoice?id=test_invoice_id',
'status': 'new'
}
client.get_invoice.return_value = {
'id': 'test_invoice_id',
'status': 'paid'
}
return client


@pytest.fixture
def env_vars(monkeypatch):
"""Set up environment variables for testing."""
monkeypatch.setenv('BTCPAY_HOST', 'https://testnet.demo.btcpayserver.org')
monkeypatch.setenv('BTCPAY_PRIVATE_KEY', 'test_private_key')
monkeypatch.setenv('BTCPAY_MERCHANT_TOKEN', 'test_merchant_token')
Empty file added tests/integration/__init__.py
Empty file.
71 changes: 71 additions & 0 deletions tests/test_setup_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""Validation tests to ensure the testing infrastructure is properly configured."""

import pytest
import sys
import os


def test_python_version():
"""Test that Python version is supported."""
assert sys.version_info >= (3, 6), "Python 3.6+ is required"


def test_pytest_markers():
"""Test that custom pytest markers are registered."""
expected_markers = ["unit", "integration", "slow"]
for marker in expected_markers:
assert marker is not None, f"Marker {marker} should be available"


def test_btcpay_package_importable():
"""Test that the btcpay package can be imported."""
try:
import btcpay
assert btcpay is not None
except ImportError as e:
pytest.fail(f"Could not import btcpay package: {e}")


def test_pytest_configured():
"""Test that pytest is properly configured."""
import _pytest.config
assert _pytest.config is not None


@pytest.mark.unit
def test_unit_marker():
"""Test that unit marker works."""
assert True


@pytest.mark.integration
def test_integration_marker():
"""Test that integration marker works."""
assert True


@pytest.mark.slow
def test_slow_marker():
"""Test that slow marker works."""
assert True


def test_temp_dir_fixture(temp_dir):
"""Test that temp_dir fixture works."""
assert os.path.exists(temp_dir)
assert os.path.isdir(temp_dir)


def test_mock_config_fixture(mock_config):
"""Test that mock_config fixture works."""
assert isinstance(mock_config, dict)
assert 'api_url' in mock_config
assert 'pem' in mock_config
assert 'tokens' in mock_config


def test_sample_invoice_data_fixture(sample_invoice_data):
"""Test that sample_invoice_data fixture works."""
assert isinstance(sample_invoice_data, dict)
assert 'price' in sample_invoice_data
assert 'currency' in sample_invoice_data
Empty file added tests/unit/__init__.py
Empty file.