File size: 6,873 Bytes
d1564d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#!/usr/bin/env python3
"""
E2E Test Runner Script

Script to run end-to-end tests for the AI Due Diligence application.
Provides options for different test suites and configurations.
"""

import os
import sys
import subprocess
import argparse
import time
from pathlib import Path

# Add project root to Python path
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))


def run_command(cmd, description="", timeout=None):
    """Run a command with error handling"""
    print(f"\nπŸ”§ {description}")
    print(f"Running: {' '.join(cmd)}")
    
    try:
        result = subprocess.run(
            cmd,
            check=True,
            capture_output=True,
            text=True,
            timeout=timeout,
            cwd=project_root
        )
        print("βœ… Success")
        return True, result.stdout, result.stderr
    except subprocess.CalledProcessError as e:
        print(f"❌ Failed with exit code {e.returncode}")
        print(f"STDOUT: {e.stdout}")
        print(f"STDERR: {e.stderr}")
        return False, e.stdout, e.stderr
    except subprocess.TimeoutExpired as e:
        print(f"⏰ Timeout after {timeout} seconds")
        return False, "", str(e)


def check_prerequisites():
    """Check that all prerequisites are available"""
    print("πŸ” Checking prerequisites...")
    
    # Check if uv is available
    success, _, _ = run_command(["uv", "--version"], "Checking uv")
    if not success:
        print("❌ uv is not available. Please install uv first.")
        return False
    
    # Check if Playwright browsers are installed
    success, _, _ = run_command(["uv", "run", "playwright", "install", "--dry-run"], "Checking Playwright browsers")
    if not success:
        print("⚠️  Playwright browsers may need to be installed")
        print("Run: uv run playwright install chromium")
    
    # Check if main app file exists
    app_file = project_root / "app" / "main.py"
    if not app_file.exists():
        print(f"❌ Main app file not found: {app_file}")
        return False
    
    print("βœ… Prerequisites check completed")
    return True


def run_smoke_tests():
    """Run smoke tests (basic functionality)"""
    cmd = [
        "uv", "run", "pytest", 
        "-c", "pytest-e2e.ini",
        "tests/e2e/test_app_startup.py",
        "-m", "not slow",
        "--maxfail=3"
    ]
    
    return run_command(cmd, "Running smoke tests", timeout=300)


def run_full_tests():
    """Run all E2E tests"""
    cmd = [
        "uv", "run", "pytest", 
        "-c", "pytest-e2e.ini",
        "tests/e2e/",
        "--maxfail=5"
    ]
    
    return run_command(cmd, "Running full E2E test suite", timeout=1200)


def run_performance_tests():
    """Run performance tests"""
    cmd = [
        "uv", "run", "pytest", 
        "-c", "pytest-e2e.ini",
        "tests/e2e/test_performance.py",
        "-m", "not slow"
    ]
    
    return run_command(cmd, "Running performance tests", timeout=600)


def run_ai_tests():
    """Run AI analysis tests"""
    cmd = [
        "uv", "run", "pytest", 
        "-c", "pytest-e2e.ini",
        "tests/e2e/test_ai_analysis.py",
        "-m", "not slow"
    ]
    
    return run_command(cmd, "Running AI analysis tests", timeout=600)


def run_custom_tests(test_path, markers=None):
    """Run custom test selection"""
    cmd = [
        "uv", "run", "pytest", 
        "-c", "pytest-e2e.ini",
        test_path
    ]
    
    if markers:
        cmd.extend(["-m", markers])
    
    return run_command(cmd, f"Running custom tests: {test_path}", timeout=900)


def install_browsers():
    """Install Playwright browsers"""
    cmd = ["uv", "run", "playwright", "install", "chromium"]
    return run_command(cmd, "Installing Playwright browsers", timeout=300)


def main():
    """Main entry point"""
    parser = argparse.ArgumentParser(description="Run E2E tests for AI Due Diligence app")
    parser.add_argument(
        "--suite", 
        choices=["smoke", "full", "performance", "ai", "custom"],
        default="smoke",
        help="Test suite to run (default: smoke)"
    )
    parser.add_argument(
        "--test-path",
        help="Specific test path (for custom suite)"
    )
    parser.add_argument(
        "--markers",
        help="Pytest markers to filter tests (e.g., 'not slow')"
    )
    parser.add_argument(
        "--install-browsers",
        action="store_true",
        help="Install Playwright browsers before running tests"
    )
    parser.add_argument(
        "--skip-checks",
        action="store_true",
        help="Skip prerequisite checks"
    )
    parser.add_argument(
        "--headless",
        action="store_true",
        default=True,
        help="Run tests in headless mode (default: True)"
    )
    parser.add_argument(
        "--headed",
        action="store_true",
        help="Run tests in headed mode (for debugging)"
    )
    
    args = parser.parse_args()
    
    print("πŸš€ AI Due Diligence E2E Test Runner")
    print("=" * 50)
    
    # Set environment variables
    if args.headed:
        os.environ["PLAYWRIGHT_HEADLESS"] = "false"
    else:
        os.environ["PLAYWRIGHT_HEADLESS"] = "true"
    
    # Check prerequisites
    if not args.skip_checks:
        if not check_prerequisites():
            sys.exit(1)
    
    # Install browsers if requested
    if args.install_browsers:
        success, _, _ = install_browsers()
        if not success:
            print("❌ Failed to install browsers")
            sys.exit(1)
    
    # Run selected test suite
    success = False
    
    if args.suite == "smoke":
        success, _, _ = run_smoke_tests()
    elif args.suite == "full":
        success, _, _ = run_full_tests()
    elif args.suite == "performance":
        success, _, _ = run_performance_tests()
    elif args.suite == "ai":
        success, _, _ = run_ai_tests()
    elif args.suite == "custom":
        if not args.test_path:
            print("❌ --test-path is required for custom suite")
            sys.exit(1)
        success, _, _ = run_custom_tests(args.test_path, args.markers)
    
    # Summary
    print("\n" + "=" * 50)
    if success:
        print("βœ… E2E tests completed successfully!")
        print("\nπŸ’‘ Tips:")
        print("  - Run with --headed to see the browser in action")
        print("  - Use --suite=full for comprehensive testing")
        print("  - Use --markers='not slow' to skip long-running tests")
    else:
        print("❌ E2E tests failed!")
        print("\nπŸ”§ Troubleshooting:")
        print("  - Make sure the Streamlit app can start properly")
        print("  - Check that all dependencies are installed")
        print("  - Try running with --install-browsers first")
        print("  - Run individual tests to isolate issues")
        sys.exit(1)


if __name__ == "__main__":
    main()