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
14 changes: 13 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,16 @@ dmypy.json
*.pdf
/*.sh
/*.py
local_json_data/
local_json_data/

# Claude
.claude/*

# Poetry
# Do not ignore poetry.lock - it should be committed
dist/
.pytest_cache/
htmlcov/
coverage.xml
.coverage
.coverage.*
1 change: 1 addition & 0 deletions code/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""ICCV 2023 Paper Analysis code package."""
851 changes: 851 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

86 changes: 86 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
[tool.poetry]
name = "iccv2023-paper-analysis"
version = "0.1.0"
description = "ICCV 2023 Paper Analysis Project"
authors = ["Your Name <[email protected]>"]
readme = "README.md"
packages = [{include = "code"}]

[tool.poetry.dependencies]
python = "^3.8"
beautifulsoup4 = "^4.12.0"
markdown2 = "^2.4.0"
prettytable = "^3.9.0"
PyGithub = "^2.1.0"

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

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

[tool.pytest.ini_options]
minversion = "8.0"
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"--strict-markers",
"--verbose",
"-ra",
"--cov=code",
"--cov-report=term-missing:skip-covered",
"--cov-report=html",
"--cov-report=xml",
"--cov-fail-under=0", # Set to 0 for infrastructure setup, change to 80 when adding real tests
]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Slow running tests",
]
filterwarnings = [
"error",
"ignore::UserWarning",
"ignore::DeprecationWarning",
]

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

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if __name__ == .__main__.:",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if False:",
"pass",
]
show_missing = true
precision = 2
fail_under = 0 # Set to 0 for infrastructure setup, change to 80 when adding real tests

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

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

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Empty file added tests/__init__.py
Empty file.
157 changes: 157 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
"""Shared pytest fixtures and configuration."""

import json
import tempfile
from pathlib import Path
from unittest.mock import Mock

import pytest


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


@pytest.fixture
def sample_markdown_content():
"""Sample markdown content for testing."""
return """# Recognition: Detection

## Main Conference

| Title | Links | Paper | Video |
|-------|-------|-------|-------|
| [Sample Paper Title](https://example.com/paper) | [![GitHub](https://img.shields.io/badge/GitHub-Repository-blue)](https://github.com/user/repo) | [![thecvf](https://img.shields.io/badge/pdf-thecvf-green)](https://example.com/paper.pdf) | [![YouTube](https://img.shields.io/badge/YouTube-Video-red)](https://youtube.com/watch?v=123) |
"""


@pytest.fixture
def sample_json_data():
"""Sample JSON data structure for testing."""
return [
{
"title": "Sample Paper Title",
"base_url": "https://example.com",
"title_page": "/paper",
"ieee_id": None,
"github": "user/repo",
"web_page": None,
"github_page": None,
"colab": None,
"modelscope": None,
"gitee": None,
"gitlab": None,
"zenodo": None,
"kaggle": None,
"demo_page": None,
"paper_thecvf": "/paper.pdf",
"paper_arxiv_id": None,
"paper_pdf": None,
"paper_hal_science": None,
"paper_researchgate": None,
"paper_amazon": None,
"youtube_id": "123",
"drive_google": None,
"dropbox": None,
"onedrive": None,
"loom": None,
"section": "Recognition: Detection"
}
]


@pytest.fixture
def mock_config(monkeypatch):
"""Mock configuration values for testing."""
monkeypatch.setenv("GITHUB_REPOSITORY", "test-owner/test-repo")
monkeypatch.setenv("GITHUB_TOKEN", "test-token")
monkeypatch.setenv("GITHUB_WORKSPACE", "/test/workspace")

class MockConfig:
GITHUB_TOKEN = "test-token"
GITHUB_WORKSPACE = "/test/workspace"
MARKDOWN_DIRECTORY = "sections"
OUTPUT_DIRECTORY = "json_data"
MARKDOWN_DIRECTORY_LOCAL = Path("./sections").resolve()
OUTPUT_DIRECTORY_LOCAL = Path("./local_json_data").resolve()
REPO_OWNER = "test-owner"
REPO_NAME = "test-repo"
COMMIT_MESSAGE = "Update files"

return MockConfig


@pytest.fixture
def mock_github_repo():
"""Mock GitHub repository for testing."""
mock_repo = Mock()
mock_repo.default_branch = "main"
mock_repo.get_branch.return_value.commit.sha = "abc123"
mock_repo.get_git_commit.return_value.tree.sha = "tree123"
mock_repo.create_git_tree.return_value.sha = "newtree123"
mock_repo.create_git_commit.return_value.sha = "newcommit123"
return mock_repo


@pytest.fixture
def sample_html_content():
"""Sample HTML content for testing BeautifulSoup parsing."""
return """
<h2>Recognition: Detection</h2>
<table>
<tr>
<th>Title</th>
<th>Links</th>
<th>Paper</th>
<th>Video</th>
</tr>
<tr>
<td><a href="/paper">Sample Paper Title</a></td>
<td>
<a href="https://github.com/user/repo">
<img alt="GitHub" src="github.png">
</a>
</td>
<td>
<a href="/paper.pdf">
<img alt="thecvf" src="pdf.png">
</a>
</td>
<td>
<a href="https://youtube.com/watch?v=123">
<img alt="Video" src="video.png">
</a>
</td>
</tr>
</table>
"""


@pytest.fixture
def create_test_file(temp_dir):
"""Factory fixture to create test files."""
def _create_file(filename, content):
file_path = temp_dir / filename
file_path.parent.mkdir(parents=True, exist_ok=True)
file_path.write_text(content)
return file_path
return _create_file


@pytest.fixture
def mock_beautiful_soup(monkeypatch):
"""Mock BeautifulSoup for testing without actual HTML parsing."""
def mock_init(self, *args, **kwargs):
pass

monkeypatch.setattr("bs4.BeautifulSoup.__init__", mock_init)


@pytest.fixture
def capture_logs(caplog):
"""Capture log messages during tests."""
with caplog.at_level("INFO"):
yield caplog
Empty file added tests/integration/__init__.py
Empty file.
102 changes: 102 additions & 0 deletions tests/test_infrastructure_validation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Validation tests to verify the testing infrastructure is properly set up."""

import json
from pathlib import Path

import pytest


class TestInfrastructureValidation:
"""Test class to validate the testing infrastructure setup."""

def test_pytest_is_working(self):
"""Basic test to verify pytest is working."""
assert True
assert 1 + 1 == 2

def test_fixtures_are_available(self, temp_dir, sample_markdown_content):
"""Test that fixtures from conftest.py are accessible."""
assert isinstance(temp_dir, Path)
assert temp_dir.exists()
assert isinstance(sample_markdown_content, str)
assert "Recognition: Detection" in sample_markdown_content

def test_temp_dir_fixture_creates_directory(self, temp_dir):
"""Test that temp_dir fixture creates a working directory."""
test_file = temp_dir / "test.txt"
test_file.write_text("Hello, testing!")

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

def test_create_test_file_fixture(self, create_test_file):
"""Test the create_test_file factory fixture."""
test_file = create_test_file("subdir/test.json", '{"key": "value"}')

assert test_file.exists()
assert test_file.parent.name == "subdir"

data = json.loads(test_file.read_text())
assert data == {"key": "value"}

@pytest.mark.unit
def test_unit_marker(self):
"""Test that unit test marker is working."""
assert True

@pytest.mark.integration
def test_integration_marker(self):
"""Test that integration test marker is working."""
assert True

@pytest.mark.slow
def test_slow_marker(self):
"""Test that slow test marker is working."""
assert True

def test_mock_fixtures_available(self, mock_config, mock_github_repo):
"""Test that mock fixtures are available and working."""
assert mock_config.GITHUB_TOKEN == "test-token"
assert mock_config.REPO_OWNER == "test-owner"
assert mock_github_repo.default_branch == "main"

def test_sample_json_data_fixture(self, sample_json_data):
"""Test the sample JSON data fixture."""
assert isinstance(sample_json_data, list)
assert len(sample_json_data) == 1
assert sample_json_data[0]["title"] == "Sample Paper Title"
assert sample_json_data[0]["github"] == "user/repo"

def test_coverage_is_tracked(self):
"""Test that code coverage is being tracked."""
# This test ensures coverage reporting works
def dummy_function(x):
if x > 0:
return x * 2
else:
return 0

assert dummy_function(5) == 10
assert dummy_function(-1) == 0

def test_pytest_mock_is_available(self, mocker):
"""Test that pytest-mock is installed and working."""
mock_func = mocker.Mock(return_value=42)
assert mock_func() == 42
mock_func.assert_called_once()

def test_parameterized_tests(self):
"""Test that pytest parametrization works."""

@pytest.mark.parametrize("input_val,expected", [
(1, 2),
(2, 4),
(3, 6),
])
def inner_test(input_val, expected):
assert input_val * 2 == expected

# Run the parameterized test
inner_test(1, 2)
inner_test(2, 4)
inner_test(3, 6)
Empty file added tests/unit/__init__.py
Empty file.