""" 性能测试模块 测试网站性能指标 """ import pytest import time from typing import Dict, Any from datetime import datetime from pages.home_page import HomePage from pages.contact_page import ContactPage from config.settings import get_settings class TestPerformance: """性能测试类""" @pytest.mark.performance @pytest.mark.smoke def test_home_page_load_time(self, home_page: HomePage): """测试首页加载时间""" home_page.navigate() start_time = time.time() home_page.wait_for_load() end_time = time.time() load_time = (end_time - start_time) * 1000 # 毫秒 # 阈值:5秒 assert load_time < 5000, f"首页加载时间 {load_time:.2f}ms 超过5秒阈值" @pytest.mark.performance @pytest.mark.smoke def test_contact_page_load_time(self, contact_page: ContactPage): """测试联系页面加载时间""" contact_page.navigate() start_time = time.time() contact_page.wait_for_load() end_time = time.time() load_time = (end_time - start_time) * 1000 # 阈值:5秒 assert load_time < 5000, f"联系页面加载时间 {load_time:.2f}ms 超过5秒阈值" @pytest.mark.performance def test_dom_content_loaded_time(self, home_page: HomePage): """测试DOM内容加载时间""" home_page.navigate() performance_data = home_page.execute_js(""" () => { const timing = performance.timing; return { domContentLoaded: timing.domContentLoadedEventEnd - timing.navigationStart, domInteractive: timing.domInteractive - timing.domLoading }; } """) dom_loaded = performance_data.get("domContentLoaded", 0) assert dom_loaded < 3000, f"DOM内容加载时间 {dom_loaded}ms 超过3秒阈值" @pytest.mark.performance def test_first_paint_time(self, home_page: HomePage): """测试首次绘制时间""" home_page.navigate() first_paint = home_page.execute_js(""" () => { const entries = performance.getEntriesByType('paint'); const firstPaint = entries.find(e => e.name === 'first-paint'); return firstPaint ? firstPaint.startTime : 0; } """) if first_paint: assert first_paint < 2000, f"首次绘制时间 {first_paint:.2f}ms 超过2秒阈值" @pytest.mark.performance def test_first_contentful_paint(self, home_page: HomePage): """测试首次内容绘制(FCP)""" home_page.navigate() fcp = home_page.execute_js(""" () => { const navigation = performance.getEntriesByType('navigation')[0]; return navigation ? navigation.firstContentfulPaint : 0; } """) if fcp: # 阈值:1.5秒 assert fcp < 1500, f"首次内容绘制时间 {fcp:.2f}ms 超过1.5秒阈值" @pytest.mark.performance def test_largest_contentful_paint(self, home_page: HomePage): """测试最大内容绘制(LCP)""" home_page.navigate() lcp = home_page.execute_js(""" () => { try { const navigation = performance.getEntriesByType('navigation')[0]; return navigation ? navigation.largestContentfulPaint : 0; } catch (e) { return 0; } } """) if lcp: # 阈值:2.5秒 assert lcp < 2500, f"最大内容绘制时间 {lcp:.2f}ms 超过2.5秒阈值" @pytest.mark.performance def test_time_to_interactive(self, home_page: HomePage): """测试可交互时间(TTI)""" home_page.navigate() tti = home_page.execute_js(""" () => { try { const navigation = performance.getEntriesByType('navigation')[0]; return navigation ? navigation.interactive : 0; } catch (e) { return 0; } } """) if tti: # 阈值:3秒 assert tti < 3000, f"可交互时间 {tti:.2f}ms 超过3秒阈值" @pytest.mark.performance def test_page_load_performance_metrics(self, home_page: HomePage): """测试页面加载性能指标""" home_page.navigate() performance = home_page.verify_page_performance() # 验证关键指标 if performance.get("pageLoadTime"): assert performance["pageLoadTime"] < 5000 if performance.get("domContentLoaded"): assert performance["domContentLoaded"] < 3000 @pytest.mark.performance def test_network_timing(self, home_page: HomePage): """测试网络时序""" home_page.navigate() timing = home_page.execute_js(""" () => { const timing = performance.timing; return { dnsLookup: timing.domainLookupEnd - timing.domainLookupStart, tcpConnection: timing.connectEnd - timing.connectStart, serverResponse: timing.responseEnd - timing.requestStart, domProcessing: timing.domLoading - timing.responseEnd }; } """) # DNS查询时间 assert timing.get("dnsLookup", 0) < 500, \ f"DNS查询时间 {timing.get('dnsLookup')}ms 超过500ms阈值" # TCP连接时间 assert timing.get("tcpConnection", 0) < 500, \ f"TCP连接时间 {timing.get('tcpConnection')}ms 超过500ms阈值" # 服务器响应时间 assert timing.get("serverResponse", 0) < 1000, \ f"服务器响应时间 {timing.get('serverResponse')}ms 超过1秒阈值" @pytest.mark.performance def test_resource_timing(self, home_page: HomePage): """测试资源加载时序""" home_page.navigate() resources = home_page.execute_js(""" () => { const entries = performance.getEntriesByType('resource'); const scripts = entries.filter(e => e.initiatorType === 'script'); const styles = entries.filter(e => e.initiatorType === 'css'); return { totalResources: entries.length, scriptCount: scripts.length, styleCount: styles.length, totalDuration: entries.reduce((sum, e) => sum + e.duration, 0) }; } """) assert resources.get("totalResources", 0) > 0, "未检测到资源加载" home_page.logger.info( f"资源统计: 共{resources.get('totalResources')}个资源," f"脚本{resources.get('scriptCount')}个," f"样式{resources.get('styleCount')}个" ) @pytest.mark.performance def test_form_submission_time(self, contact_page: ContactPage, test_data_generator): """测试表单提交时间""" contact_page.navigate() data = test_data_generator.generate_contact_form_data(use_valid=True) start_time = time.time() contact_page.fill_contact_form(data) contact_page.submit_form() try: contact_page.verify_form_submission_success() except Exception: pass end_time = time.time() duration = (end_time - start_time) * 1000 # 阈值:30秒(开发环境可能较慢) assert duration < 30000, f"表单提交耗时 {duration:.2f}ms 超过30秒阈值" @pytest.mark.performance def test_scroll_performance(self, home_page: HomePage): """测试滚动性能""" home_page.navigate() # 执行多次滚动 scroll_times = [] for i in range(5): start_time = time.time() home_page.scroll_to_bottom() home_page.scroll_to_top() end_time = time.time() scroll_times.append((end_time - start_time) * 1000) avg_scroll_time = sum(scroll_times) / len(scroll_times) # 平均滚动时间应该在1秒内 assert avg_scroll_time < 1000, f"平均滚动时间 {avg_scroll_time:.2f}ms 超过1秒阈值" @pytest.mark.performance def test_element_visibility_performance(self, home_page: HomePage): """测试元素可见性检查性能""" home_page.navigate() elements = [ "header", "main", "footer", "h1", "nav", "section:first-of-type", "form", "button" ] check_times = [] for element in elements: start_time = time.time() try: home_page._is_visible(element) except Exception: pass end_time = time.time() check_times.append((end_time - start_time) * 1000) avg_check_time = sum(check_times) / len(check_times) # 单个元素检查时间应该在3000ms内(开发环境) assert avg_check_time < 3000, f"平均元素检查时间 {avg_check_time:.2f}ms 超过3000ms阈值" @pytest.mark.performance def test_navigation_performance(self, home_page: HomePage, contact_page: ContactPage): """测试导航性能""" # 测量导航到联系页面的时间 start_time = time.time() contact_page.navigate() contact_page.wait_for_load() end_time = time.time() nav_time = (end_time - start_time) * 1000 # 阈值:3秒 assert nav_time < 3000, f"导航时间 {nav_time:.2f}ms 超过3秒阈值" @pytest.mark.performance @pytest.mark.responsive def test_performance_across_viewports(self, home_page: HomePage): """测试不同视口下的性能""" viewports = [ (375, 667, "移动端"), (768, 1024, "平板端"), (1920, 1080, "桌面端") ] results = [] for width, height, name in viewports: home_page.page.set_viewport_size({"width": width, "height": height}) start_time = time.time() home_page.navigate() home_page.wait_for_load() end_time = time.time() load_time = (end_time - start_time) * 1000 results.append((name, load_time)) home_page.logger.info(f"{name} ({width}x{height}): {load_time:.2f}ms") # 验证所有视口加载时间在阈值内 for name, load_time in results: assert load_time < 5000, f"{name}加载时间 {load_time:.2f}ms 超过5秒阈值"