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
43 changes: 42 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,42 @@
**/.DS_Store
**/.DS_Store

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
venv/
.venv/
ENV/
env.bak/
venv.bak/

# Testing
.pytest_cache/
.coverage
htmlcov/
coverage.xml
*.cover
.hypothesis/
.tox/

# Poetry
dist/
build/
*.egg-info/

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

# Claude
.claude/*

# Project specific
gpt4/
test_output/
700 changes: 700 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
[tool.poetry]
name = "prompting-guide"
version = "0.1.0"
description = "A comprehensive guide for prompting techniques and principles"
authors = ["Your Name <you@example.com>"]
readme = "README.md"
license = "MIT"
packages = [{include = "src", from = "."}]

[tool.poetry.dependencies]
python = "^3.8"
openai = "^1.0.0"

[tool.poetry.group.dev.dependencies]
pytest = "^8.0.0"
pytest-cov = "^5.0.0"
pytest-mock = "^3.14.0"

[tool.poetry.scripts]
test = "pytest:main"
tests = "pytest:main"

[tool.pytest.ini_options]
minversion = "8.0"
addopts = [
"--strict-markers",
"--strict-config",
"--verbose",
"--cov=src",
"--cov-branch",
"--cov-report=term-missing:skip-covered",
"--cov-report=html:htmlcov",
"--cov-report=xml:coverage.xml",
"--cov-fail-under=15",
]
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Tests that take a long time to run",
]

[tool.coverage.run]
source = ["src"]
branch = true
omit = [
"*/tests/*",
"*/__pycache__/*",
"*/venv/*",
"*/.venv/*",
"*/site-packages/*",
]

[tool.coverage.report]
precision = 2
show_missing = true
skip_covered = false
fail_under = 15
exclude_lines = [
"pragma: no cover",
"def __repr__",
"raise AssertionError",
"raise NotImplementedError",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod",
]

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

[tool.coverage.xml]
output = "coverage.xml"

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Empty file added src/__init__.py
Empty file.
File renamed without changes.
Empty file added tests/__init__.py
Empty file.
123 changes: 123 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import pytest
import tempfile
import shutil
from pathlib import Path
from unittest.mock import Mock, patch
import json
import os


@pytest.fixture
def temp_dir():
"""Create a temporary directory for testing."""
temp_path = tempfile.mkdtemp()
yield Path(temp_path)
shutil.rmtree(temp_path)


@pytest.fixture
def mock_openai_client():
"""Mock OpenAI client for testing."""
with patch('openai.OpenAI') as mock_client:
mock_instance = Mock()
mock_client.return_value = mock_instance

# Mock completion response
mock_response = Mock()
mock_response.choices = [Mock(message=Mock(content="Test response"))]
mock_instance.chat.completions.create.return_value = mock_response

yield mock_instance


@pytest.fixture
def sample_questions_file(temp_dir):
"""Create a sample questions file for testing."""
file_path = temp_dir / "test_questions.txt"
content = """Question 1:
What is the capital of France?

Question 2:
What is 2 + 2?

Question 3:
Explain quantum physics.
"""
file_path.write_text(content)
return file_path


@pytest.fixture
def sample_json_data():
"""Provide sample JSON data for testing."""
return [
{"instruction": "What is the capital of France?", "output": "Paris"},
{"instruction": "What is 2 + 2?", "output": "4"},
]


@pytest.fixture
def mock_env_variables():
"""Mock environment variables for testing."""
with patch.dict(os.environ, {'OPENAI_KEY': 'test-api-key'}):
yield


@pytest.fixture
def mock_file_system(temp_dir):
"""Create a mock file system structure for testing."""
# Create directories
(temp_dir / "principles").mkdir()
(temp_dir / "gpt4").mkdir()

# Create sample principle files
for i in range(1, 4):
file_path = temp_dir / "principles" / f"principle_{i}.txt"
file_path.write_text(f"Question {i}:\\nSample question {i}")

return temp_dir


@pytest.fixture(autouse=True)
def cleanup_test_artifacts():
"""Automatically clean up any test artifacts after each test."""
yield
# Clean up any test-generated files
test_output_dirs = ['gpt4', 'test_output']
for dir_name in test_output_dirs:
if os.path.exists(dir_name):
shutil.rmtree(dir_name)


@pytest.fixture
def capture_logs():
"""Capture log messages during tests."""
import logging

class LogCapture:
def __init__(self):
self.records = []
self.handler = logging.Handler()
self.handler.emit = lambda record: self.records.append(record)

def __enter__(self):
logging.root.addHandler(self.handler)
return self

def __exit__(self, *args):
logging.root.removeHandler(self.handler)

def get_messages(self, level=None):
if level:
return [r.getMessage() for r in self.records if r.levelno >= level]
return [r.getMessage() for r in self.records]

return LogCapture()


@pytest.fixture
def mock_time():
"""Mock time-related functions for consistent testing."""
with patch('time.time', return_value=1234567890):
with patch('time.sleep', return_value=None):
yield
Empty file added tests/integration/__init__.py
Empty file.
110 changes: 110 additions & 0 deletions tests/test_setup_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import pytest
import sys
import os
from pathlib import Path


class TestSetupValidation:
"""Validation tests to ensure the testing infrastructure is properly set up."""

def test_python_version(self):
"""Ensure Python version is 3.8 or higher."""
assert sys.version_info >= (3, 8), "Python 3.8 or higher is required"

def test_project_structure_exists(self):
"""Verify the project directory structure is correct."""
project_root = Path(__file__).parent.parent

# Check main directories
assert project_root.exists()
assert (project_root / "tests").exists()
assert (project_root / "tests" / "unit").exists()
assert (project_root / "tests" / "integration").exists()

# Check configuration files
assert (project_root / "pyproject.toml").exists()

def test_pytest_markers_configured(self):
"""Verify pytest markers are properly configured."""
# This test verifies that our custom markers work
assert hasattr(self.test_pytest_markers_configured, '__func__')

@pytest.mark.unit
def test_unit_marker(self):
"""Test that unit marker is recognized."""
pass

@pytest.mark.integration
def test_integration_marker(self):
"""Test that integration marker is recognized."""
pass

@pytest.mark.slow
def test_slow_marker(self):
"""Test that slow marker is recognized."""
pass

def test_fixtures_available(self, temp_dir, mock_openai_client):
"""Verify that common fixtures are available."""
assert temp_dir.exists()
assert temp_dir.is_dir()
assert mock_openai_client is not None

def test_coverage_configured(self):
"""Verify coverage is properly configured."""
# This test runs as part of coverage, so if it passes, coverage is working
assert True

def test_imports_work(self, mock_env_variables):
"""Verify that we can import the main module."""
try:
from src import generate
assert hasattr(generate, 'generate_answers')
assert hasattr(generate, 'extract_questions_from_file')
except ImportError as e:
pytest.fail(f"Failed to import generate module: {e}")


class TestPoetryScripts:
"""Test that Poetry scripts are properly configured."""

def test_poetry_scripts_configured(self):
"""Verify Poetry scripts are set up in pyproject.toml."""
project_root = Path(__file__).parent.parent
pyproject_path = project_root / "pyproject.toml"

with open(pyproject_path, 'r') as f:
content = f.read()

# Check that both test and tests commands are configured
assert '[tool.poetry.scripts]' in content
assert 'test = "pytest:main"' in content
assert 'tests = "pytest:main"' in content


@pytest.mark.unit
class TestMockingCapabilities:
"""Test that mocking utilities work correctly."""

def test_mock_environment_variables(self, mock_env_variables):
"""Test environment variable mocking."""
assert os.environ.get('OPENAI_KEY') == 'test-api-key'

def test_mock_file_operations(self, temp_dir):
"""Test file operation mocking."""
test_file = temp_dir / "test.txt"
test_file.write_text("Hello, World!")

assert test_file.exists()
assert test_file.read_text() == "Hello, World!"

def test_json_operations(self, sample_json_data):
"""Test JSON data handling."""
import json

json_str = json.dumps(sample_json_data)
parsed = json.loads(json_str)

assert len(parsed) == 2
assert parsed[0]["instruction"] == "What is the capital of France?"
assert parsed[1]["output"] == "4"
Empty file added tests/unit/__init__.py
Empty file.