131 lines
4.3 KiB
Python
131 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Adds StellaOps.TestKit ProjectReference to test projects that use TestCategories
|
|
but are missing the reference.
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
def get_relative_path_to_testkit(csproj_path: Path) -> str:
|
|
"""Calculate relative path from csproj to TestKit project."""
|
|
# TestKit is at src/__Libraries/StellaOps.TestKit/StellaOps.TestKit.csproj
|
|
csproj_dir = csproj_path.parent
|
|
src_root = None
|
|
|
|
# Walk up to find src directory
|
|
current = csproj_dir
|
|
depth = 0
|
|
while current.name != 'src' and depth < 10:
|
|
current = current.parent
|
|
depth += 1
|
|
|
|
if current.name == 'src':
|
|
src_root = current
|
|
else:
|
|
return None
|
|
|
|
# Calculate relative path from csproj to src/__Libraries/StellaOps.TestKit
|
|
rel_path = os.path.relpath(
|
|
src_root / '__Libraries' / 'StellaOps.TestKit' / 'StellaOps.TestKit.csproj',
|
|
csproj_dir
|
|
)
|
|
# Normalize to forward slashes for XML
|
|
return rel_path.replace('\\', '/')
|
|
|
|
|
|
def project_uses_testkit(csproj_dir: Path) -> bool:
|
|
"""Check if any .cs file in the project directory uses TestCategories."""
|
|
for cs_file in csproj_dir.rglob('*.cs'):
|
|
if '/obj/' in str(cs_file) or '/bin/' in str(cs_file):
|
|
continue
|
|
try:
|
|
content = cs_file.read_text(encoding='utf-8-sig', errors='ignore')
|
|
if 'TestCategories.' in content:
|
|
return True
|
|
except:
|
|
pass
|
|
return False
|
|
|
|
|
|
def project_has_testkit_reference(content: str) -> bool:
|
|
"""Check if csproj already references TestKit."""
|
|
return 'StellaOps.TestKit' in content
|
|
|
|
|
|
def add_testkit_reference(csproj_path: Path, dry_run: bool = False) -> bool:
|
|
"""Add TestKit reference to csproj if needed."""
|
|
try:
|
|
content = csproj_path.read_text(encoding='utf-8')
|
|
except Exception as e:
|
|
print(f" Error reading {csproj_path}: {e}", file=sys.stderr)
|
|
return False
|
|
|
|
if project_has_testkit_reference(content):
|
|
return False
|
|
|
|
if not project_uses_testkit(csproj_path.parent):
|
|
return False
|
|
|
|
rel_path = get_relative_path_to_testkit(csproj_path)
|
|
if not rel_path:
|
|
print(f" Could not determine path to TestKit from {csproj_path}", file=sys.stderr)
|
|
return False
|
|
|
|
# Find a good place to insert the reference - look for existing ProjectReference
|
|
if '<ProjectReference' in content:
|
|
# Insert before the last </ItemGroup> that contains ProjectReference
|
|
pattern = r'( <ProjectReference [^>]+/>\s*\n)( </ItemGroup>)'
|
|
replacement = f'\\1 <ProjectReference Include="{rel_path}" />\n\\2'
|
|
fixed = re.sub(pattern, replacement, content, count=1)
|
|
else:
|
|
# No ProjectReference, add a new ItemGroup before </Project>
|
|
pattern = r'(</Project>)'
|
|
new_item_group = f''' <ItemGroup>
|
|
<ProjectReference Include="{rel_path}" />
|
|
</ItemGroup>
|
|
\\1'''
|
|
fixed = re.sub(pattern, new_item_group, content)
|
|
|
|
if fixed == content:
|
|
print(f" Could not find insertion point in {csproj_path}", file=sys.stderr)
|
|
return False
|
|
|
|
if not dry_run:
|
|
csproj_path.write_text(fixed, encoding='utf-8')
|
|
|
|
return True
|
|
|
|
|
|
def main():
|
|
import argparse
|
|
parser = argparse.ArgumentParser(description='Add TestKit reference to test projects')
|
|
parser.add_argument('--path', default='src', help='Path to scan')
|
|
parser.add_argument('--dry-run', action='store_true', help='Show what would be fixed')
|
|
args = parser.parse_args()
|
|
|
|
root = Path(args.path)
|
|
fixed_count = 0
|
|
|
|
# Find all test project files
|
|
for csproj in root.rglob('*.Tests.csproj'):
|
|
if add_testkit_reference(csproj, dry_run=args.dry_run):
|
|
print(f"{'Would add' if args.dry_run else 'Added'} TestKit reference to: {csproj}")
|
|
fixed_count += 1
|
|
|
|
# Also check *UnitTests, *SmokeTests, etc.
|
|
for pattern in ['*UnitTests.csproj', '*IntegrationTests.csproj', '*SmokeTests.csproj', '*FixtureTests.csproj']:
|
|
for csproj in root.rglob(pattern):
|
|
if add_testkit_reference(csproj, dry_run=args.dry_run):
|
|
print(f"{'Would add' if args.dry_run else 'Added'} TestKit reference to: {csproj}")
|
|
fixed_count += 1
|
|
|
|
print(f"\nAdded TestKit reference to: {fixed_count} projects")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|