mirror of
https://github.com/researchobjectschema/ro-crate-interoperability-profile.git
synced 2026-03-08 01:37:46 +01:00
206 lines
7.2 KiB
Python
206 lines
7.2 KiB
Python
"""
|
|
Test that verifies the published package can be installed and used from TestPyPI.
|
|
|
|
This test creates an isolated environment, installs the package from TestPyPI,
|
|
and runs a quickstart-style example to ensure everything works as expected.
|
|
"""
|
|
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
|
|
def test_install_from_testpypi():
|
|
"""
|
|
Test that the package can be installed from TestPyPI and basic functionality works.
|
|
|
|
This test:
|
|
1. Creates a temporary virtual environment
|
|
2. Installs the package from TestPyPI
|
|
3. Runs a simple example similar to quickstart
|
|
4. Verifies the output is correct
|
|
"""
|
|
|
|
# Create a temporary directory for our test environment
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
venv_path = Path(tmpdir) / "test_venv"
|
|
|
|
print(f"\n{'='*60}")
|
|
print("Testing Published Package from TestPyPI")
|
|
print(f"{'='*60}")
|
|
|
|
# Step 1: Create virtual environment
|
|
print("\n1. Creating virtual environment...")
|
|
result = subprocess.run(
|
|
[sys.executable, "-m", "venv", str(venv_path)],
|
|
capture_output=True,
|
|
text=True
|
|
)
|
|
assert result.returncode == 0, f"Failed to create venv: {result.stderr}"
|
|
print(" ✓ Virtual environment created")
|
|
|
|
# Determine pip executable path
|
|
if sys.platform == "win32":
|
|
pip_path = venv_path / "Scripts" / "pip"
|
|
python_path = venv_path / "Scripts" / "python"
|
|
else:
|
|
pip_path = venv_path / "bin" / "pip"
|
|
python_path = venv_path / "bin" / "python"
|
|
|
|
# Step 2: Install from TestPyPI
|
|
print("\n2. Installing lib-ro-crate-schema from TestPyPI...")
|
|
print(" Note: Package may take a few minutes to be indexed on TestPyPI")
|
|
|
|
# Try with the specific version (0.2.0 is available on TestPyPI)
|
|
result = subprocess.run(
|
|
[
|
|
str(pip_path),
|
|
"install",
|
|
"--index-url", "https://test.pypi.org/simple/",
|
|
"--extra-index-url", "https://pypi.org/simple/",
|
|
"lib-ro-crate-schema==0.2.0"
|
|
],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=120
|
|
)
|
|
|
|
if result.returncode != 0:
|
|
print(f" ✗ Installation failed!")
|
|
print(f" stdout: {result.stdout}")
|
|
print(f" stderr: {result.stderr}")
|
|
assert False, "Failed to install package from TestPyPI"
|
|
|
|
print(" ✓ Package installed successfully")
|
|
|
|
# Step 3: Create a test script similar to quickstart
|
|
print("\n3. Creating test script...")
|
|
test_script = venv_path / "test_quickstart.py"
|
|
test_script.write_text("""
|
|
# Test script that mimics the quickstart example
|
|
from pydantic import BaseModel, Field
|
|
from lib_ro_crate_schema.crate.decorators import ro_crate_schema
|
|
from lib_ro_crate_schema.crate.schema_facade import SchemaFacade
|
|
import json
|
|
from pathlib import Path
|
|
import tempfile
|
|
|
|
# Define a schema using decorators
|
|
@ro_crate_schema(ontology="https://schema.org/Person")
|
|
class Person(BaseModel):
|
|
name: str = Field(json_schema_extra={"ontology": "https://schema.org/name"})
|
|
email: str = Field(json_schema_extra={"ontology": "https://schema.org/email"})
|
|
|
|
@ro_crate_schema(ontology="https://schema.org/Organization")
|
|
class Organization(BaseModel):
|
|
name: str = Field(json_schema_extra={"ontology": "https://schema.org/name"})
|
|
url: str = Field(json_schema_extra={"ontology": "https://schema.org/url"})
|
|
|
|
# Create instances
|
|
person = Person(name="Alice Researcher", email="alice@example.org")
|
|
org = Organization(name="Research Institute", url="https://example.org")
|
|
|
|
# Create RO-Crate using the actual API
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
output_path = Path(tmpdir) / "test_crate"
|
|
|
|
# Create facade and add registered models
|
|
facade = SchemaFacade()
|
|
facade.add_all_registered_models()
|
|
|
|
# Add model instances
|
|
facade.add_model_instance(person, "alice_researcher")
|
|
facade.add_model_instance(org, "research_institute")
|
|
|
|
# Export using add_schema_to_crate
|
|
from lib_ro_crate_schema.crate.jsonld_utils import add_schema_to_crate
|
|
from rocrate.rocrate import ROCrate
|
|
|
|
crate = ROCrate()
|
|
crate.name = "Test RO-Crate"
|
|
crate.description = "Testing published package"
|
|
final_crate = add_schema_to_crate(facade, crate)
|
|
final_crate.write(output_path)
|
|
|
|
# Verify the crate was created
|
|
metadata_file = output_path / "ro-crate-metadata.json"
|
|
assert metadata_file.exists(), "ro-crate-metadata.json not created"
|
|
|
|
# Load and verify content
|
|
with open(metadata_file) as f:
|
|
metadata = json.load(f)
|
|
|
|
# Verify basic structure
|
|
assert "@context" in metadata, "Missing @context"
|
|
assert "@graph" in metadata, "Missing @graph"
|
|
|
|
# Count entities
|
|
graph = metadata["@graph"]
|
|
|
|
# Look for our entity types
|
|
type_counts = {}
|
|
for item in graph:
|
|
entity_type = item.get("@type", "Unknown")
|
|
if isinstance(entity_type, list):
|
|
for t in entity_type:
|
|
type_counts[t] = type_counts.get(t, 0) + 1
|
|
else:
|
|
type_counts[entity_type] = type_counts.get(entity_type, 0) + 1
|
|
|
|
# Verify we have our custom types
|
|
has_person = "Person" in type_counts
|
|
has_org = "Organization" in type_counts
|
|
|
|
assert has_person or has_org, "No custom entity types found"
|
|
|
|
print("SUCCESS: All checks passed!")
|
|
print(f"- Created RO-Crate with {len(graph)} entities")
|
|
print(f"- Entity types: {', '.join(f'{k}: {v}' for k, v in sorted(type_counts.items()))}")
|
|
if has_person:
|
|
print(f"- ✓ Person entities found")
|
|
if has_org:
|
|
print(f"- ✓ Organization entities found")
|
|
""")
|
|
print(" ✓ Test script created")
|
|
|
|
# Step 4: Run the test script
|
|
print("\n4. Running test script...")
|
|
result = subprocess.run(
|
|
[str(python_path), str(test_script)],
|
|
capture_output=True,
|
|
text=True,
|
|
timeout=60
|
|
)
|
|
|
|
print("\n--- Test Script Output ---")
|
|
print(result.stdout)
|
|
if result.stderr:
|
|
print("--- Stderr ---")
|
|
print(result.stderr)
|
|
print("-------------------------\n")
|
|
|
|
if result.returncode != 0:
|
|
print(" ✗ Test script failed!")
|
|
assert False, f"Test script execution failed with code {result.returncode}"
|
|
|
|
# Verify success message
|
|
assert "SUCCESS: All checks passed!" in result.stdout, "Test did not complete successfully"
|
|
print(" ✓ Test script passed all checks")
|
|
|
|
print(f"\n{'='*60}")
|
|
print("✓ All Tests Passed!")
|
|
print(f"{'='*60}")
|
|
print("\nThe published package on TestPyPI works correctly:")
|
|
print("- Installation successful")
|
|
print("- Import successful")
|
|
print("- Decorator pattern works")
|
|
print("- RO-Crate creation works")
|
|
print("- Export functionality works")
|
|
print("- Metadata validation passed")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
test_install_from_testpypi()
|