""" SKRYPT TESTOWY TRUTHSCAN AI - TEST PORÓWNAWCZY BBC I GAZETA PRAWNA """ import requests import json import time import statistics import os from datetime import datetime from collections import defaultdict from typing import Dict, List, Any, Optional class TruthScanComparativeTester: def __init__(self, base_url="http://localhost:8000", frontend_url="http://localhost:3000"): self.base_url = base_url self.frontend_url = frontend_url self.results = [] self.errors = [] self.performance_data = [] self.bbc_results = {} self.gazeta_results = {} self.comparison_data = {} def log_test(self, test_name: str, status: str, details: str = "", duration: float = None): """Zapisuje wynik testu""" result = { "test_name": test_name, "status": status, "timestamp": datetime.now().isoformat(), "details": details, "duration": duration } self.results.append(result) status_symbol = "✅" if status == "PASS" else "❌" if status == "FAIL" else "⚠️" print(f"{status_symbol} {test_name}: {details}") if status == "FAIL": self.errors.append(result) ########## # Test dostępności API ########## def test_api_availability(self): test_name = "API Availability" start = time.time() try: response = requests.get(f"{self.base_url}/docs", timeout=10) duration = time.time() - start if response.status_code == 200: self.log_test(test_name, "PASS", f"Swagger UI dostępny ({response.status_code})", duration) return True else: self.log_test(test_name, "FAIL", f"Status code: {response.status_code}", duration) return False except Exception as e: self.log_test(test_name, "FAIL", f"Błąd połączenia: {str(e)}", time.time() - start) return False ############ # Test: Sprawdzenie dostępnych źródeł ############ def test_sources_endpoint(self): test_name = "GET /sources" start = time.time() try: response = requests.get(f"{self.base_url}/sources", timeout=15) duration = time.time() - start if response.status_code == 200: data = response.json() if isinstance(data, list): details = f"Znaleziono {len(data)} źródeł" # Sprawdzenie czy oba źródła są dostępne sources_lower = [s.lower() for s in data] bbc_available = "bbc" in sources_lower or any("bbc" in s.lower() for s in data) gazeta_available = "gazetaprawna" in sources_lower or any("gazeta" in s.lower() for s in data) if not bbc_available: details += " | ❌ BBC niedostępne" status = "WARNING" elif not gazeta_available: details += " | ❌ Gazeta Prawna niedostępne" status = "WARNING" else: details += " | ✅ BBC dostępne | ✅ Gazeta Prawna dostępne" status = "PASS" self.log_test(test_name, status, details, duration) return data else: self.log_test(test_name, "FAIL", f"Nieoczekiwany typ danych: {type(data)}", duration) return None else: self.log_test(test_name, "FAIL", f"Status code: {response.status_code}", duration) return None except Exception as e: self.log_test(test_name, "FAIL", f"Błąd: {str(e)}", time.time() - start) return None def test_single_source_detailed(self, source: str, source_name: str): print(f"\n{'='*60}") print(f"🔍 SZCZEGÓŁOWY TEST: {source_name} ({source})") print(f"{'='*60}") test_results = { "source": source, "source_name": source_name, "articles": [], "sentiment_distribution": defaultdict(int), "fake_scores": [], "performance": 0, "errors": [], "sample_titles": [] } #### Test 1: Pobieranie artykułów test_name = f"GET /news/{source}" start = time.time() try: response = requests.get(f"{self.base_url}/news/{source}", timeout=30) duration = time.time() - start test_results["performance"] = duration if response.status_code != 200: self.log_test(test_name, "FAIL", f"Status code: {response.status_code}", duration) test_results["errors"].append(f"HTTP {response.status_code}") return test_results data = response.json() if not data: self.log_test(test_name, "FAIL", "Brak danych w odpowiedzi", duration) return test_results if isinstance(data, dict) and "articles" in data: articles = data["articles"] source_from_response = data.get("source", source) test_results["articles"] = articles details = f"Pobrano {len(articles)} artykułów | Źródło: {source_from_response}" if len(articles) > 0: first_article = articles[0] available_fields = [field for field in ["title", "sentiment", "fake_probability", "summary", "link", "published"] if field in first_article] details += f" | Pola: {', '.join(available_fields)}" title = first_article.get("title", "Brak tytułu") if len(title) > 50: title = title[:50] + "..." details += f" | Przykład: '{title}'" for i, article in enumerate(articles[:3]): title = article.get("title", "") if title: test_results["sample_titles"].append(title[:80]) self.log_test(test_name, "PASS", details, duration) # Zapis danych wydajności self.performance_data.append({ "endpoint": test_name, "duration": duration, "source": source }) else: self.log_test(test_name, "WARNING", f"Nieoczekiwany format danych: {type(data)}", duration) return test_results except Exception as e: self.log_test(test_name, "FAIL", f"Błąd: {str(e)}", time.time() - start) test_results["errors"].append(str(e)) return test_results #### Test 2: Szczegółowa analiza NLP dla każdego artykułu if test_results["articles"]: print(f"\n📊 ANALIZA NLP DLA {source_name}:") for i, article in enumerate(test_results["articles"][:5]): print(f"\n 📄 Artykuł {i+1}:") title = article.get("title", "Brak tytułu") if len(title) > 60: title_display = title[:60] + "..." else: title_display = title print(f" Tytuł: {title_display}") #### Sentyment sentiment = article.get("sentiment", "Nieznany") sentiment_score = article.get("sentiment_score", 0) print(f" Sentyment: {sentiment} ({sentiment_score:.2f})") #### Fake probability fake_prob = article.get("fake_probability", 0) if isinstance(fake_prob, (int, float)): print(f" Fake probability: {fake_prob}%") #### Kategoryzacja ryzyka if fake_prob < 15: risk = "NISKIE" elif fake_prob < 30: risk = "ŚREDNIE" else: risk = "WYSOKIE" print(f" Ryzyko dezinformacji: {risk}") test_results["fake_scores"].append(fake_prob) test_results["sentiment_distribution"][sentiment] += 1 #### Link i data link = article.get("link", "") if link: domain = link.split('/')[2] if len(link.split('/')) > 2 else link print(f" Źródło: {domain}") published = article.get("published", "Brak daty") print(f" Data publikacji: {published}") #### Test 3: Analiza statystyczna if test_results["fake_scores"]: avg_fake = statistics.mean(test_results["fake_scores"]) min_fake = min(test_results["fake_scores"]) max_fake = max(test_results["fake_scores"]) print(f"\n 📈 STATYSTYKI {source_name}:") print(f" Średnie fake_probability: {avg_fake:.2f}%") print(f" Zakres: {min_fake:.2f}% - {max_fake:.2f}%") print(f" Czas odpowiedzi: {test_results['performance']:.2f}s") # Analiza rozkładu sentymentu if test_results["sentiment_distribution"]: print(f" Rozkład sentymentu:") for sentiment, count in test_results["sentiment_distribution"].items(): percentage = (count / len(test_results["articles"])) * 100 print(f" {sentiment}: {count} ({percentage:.1f}%)") return test_results ########### # Porównanie wyników BBC i Gazety Prawnej ########### def compare_sources(self, bbc_data: Dict, gazeta_data: Dict): print(f"\n{'='*60}") print(f"🔄 PORÓWNANIE BBC vs GAZETA PRAWNA") print(f"{'='*60}") # Obliczanie średnich - z obsługą pustych list bbc_fake_scores = bbc_data.get("fake_scores", []) gazeta_fake_scores = gazeta_data.get("fake_scores", []) bbc_avg_fake = statistics.mean(bbc_fake_scores) if bbc_fake_scores else 0 gazeta_avg_fake = statistics.mean(gazeta_fake_scores) if gazeta_fake_scores else 0 comparison = { "source_count": { "BBC": len(bbc_data.get("articles", [])), "Gazeta Prawna": len(gazeta_data.get("articles", [])) }, "avg_fake_score": { "BBC": bbc_avg_fake, "Gazeta Prawna": gazeta_avg_fake }, "sentiment_distribution": { "BBC": dict(bbc_data.get("sentiment_distribution", {})), "Gazeta Prawna": dict(gazeta_data.get("sentiment_distribution", {})) }, "performance": { "BBC": bbc_data.get("performance", 0), "Gazeta Prawna": gazeta_data.get("performance", 0) }, "sample_titles": { "BBC": bbc_data.get("sample_titles", []), "Gazeta Prawna": gazeta_data.get("sample_titles", []) } } #### Wyświetlanie wyników porównania print(f"\n📊 LICZBA ARTYKUŁÓW:") print(f" BBC: {comparison['source_count']['BBC']}") print(f" Gazeta Prawna: {comparison['source_count']['Gazeta Prawna']}") print(f"\n📊 ŚREDNIE RYZYKO DEZINFORMACJI:") print(f" BBC: {comparison['avg_fake_score']['BBC']:.2f}%") print(f" Gazeta Prawna: {comparison['avg_fake_score']['Gazeta Prawna']:.2f}%") #### Analiza różnic if comparison['avg_fake_score']['BBC'] > 0 and comparison['avg_fake_score']['Gazeta Prawna'] > 0: fake_diff = abs(comparison['avg_fake_score']['BBC'] - comparison['avg_fake_score']['Gazeta Prawna']) print(f" Różnica: {fake_diff:.2f}%") if fake_diff > 10: print(f" ⚠️ Znacząca różnica w ryzyku dezinformacji") print(f"\n📊 ROZKŁAD SENTYMENTU:") for source in ["BBC", "Gazeta Prawna"]: print(f"\n {source}:") dist = comparison['sentiment_distribution'][source] total = sum(dist.values()) if dist else 1 if dist: for sentiment, count in dist.items(): percentage = (count / total) * 100 if total > 0 else 0 print(f" {sentiment}: {count} ({percentage:.1f}%)") else: print(" Brak danych o sentymencie") print(f"\n📊 WYDANOŚĆ:") print(f" BBC: {comparison['performance']['BBC']:.2f}s") print(f" Gazeta Prawna: {comparison['performance']['Gazeta Prawna']:.2f}s") if comparison['performance']['BBC'] > 0 and comparison['performance']['Gazeta Prawna'] > 0: perf_diff = comparison['performance']['Gazeta Prawna'] - comparison['performance']['BBC'] if perf_diff > 1: print(f" ⏱️ Gazeta Prawna wolniejsza o {perf_diff:.2f}s (język polski)") elif perf_diff < -1: print(f" ⏱️ BBC wolniejsze o {abs(perf_diff):.2f}s") else: print(f" ⚡ Porównywalna wydajność") #### Logowanie testu porównawczego details = (f"BBC: {comparison['source_count']['BBC']} art, " f"{comparison['avg_fake_score']['BBC']:.1f}% fake, " f"{comparison['performance']['BBC']:.1f}s | " f"Gazeta: {comparison['source_count']['Gazeta Prawna']} art, " f"{comparison['avg_fake_score']['Gazeta Prawna']:.1f}% fake, " f"{comparison['performance']['Gazeta Prawna']:.1f}s") self.log_test("Source Comparison", "PASS", details) self.comparison_data = comparison return comparison ################ #Test operacji CRUD z artykułami z danego źródła ############## def test_crud_operations_for_source(self, source: str): test_name = f"CRUD Operations - {source}" ##### Najpierw pobierz artykuły ze źródła try: response = requests.get(f"{self.base_url}/news/{source}", timeout=20) if response.status_code != 200: self.log_test(test_name, "FAIL", f"Nie można pobrać artykułów: {response.status_code}") return None data = response.json() articles = data.get("articles", []) if isinstance(data, dict) else data if not articles: self.log_test(test_name, "WARNING", "Brak artykułów do testu CRUD") return None ##### Użyj pierwszego artykułu do testu test_article = articles[0] #### Dostosuj artykuł do formatu zapisu############# article_to_save = { "title": f"[TEST {source}] {test_article.get('title', 'Testowy artykuł')}", "link": test_article.get("link", "https://example.com/test"), "summary": test_article.get("summary", "Testowy artykuł do weryfikacji systemu."), "published": datetime.now().isoformat(), "sentiment": test_article.get("sentiment", "Neutral"), "fake_probability": test_article.get("fake_probability", 15.5), "source": source } operations = [] #### 1. Zapis artykułu############################# try: start = time.time() response = requests.post( f"{self.base_url}/save-article", json=article_to_save, timeout=10 ) save_time = time.time() - start if response.status_code in [200, 201]: operations.append(("Zapis", "✅", f"{save_time:.2f}s")) else: operations.append(("Zapis", "❌", f"Status: {response.status_code}")) except Exception as e: operations.append(("Zapis", "❌", f"Błąd: {str(e)[:30]}")) #### 2. Odczyt zapisanych artykułów############ try: start = time.time() response = requests.get(f"{self.base_url}/saved-articles", timeout=10) fetch_time = time.time() - start if response.status_code == 200: data = response.json() if isinstance(data, list): found = any(isinstance(a, dict) and source in a.get("title", "") for a in data) operations.append(("Odczyt", "✅" if found else "⚠️", f"{len(data)} artykułów, {fetch_time:.2f}s")) else: operations.append(("Odczyt", "❌", f"Niewłaściwy format: {type(data)}")) else: operations.append(("Odczyt", "❌", f"Status: {response.status_code}")) except Exception as e: operations.append(("Odczyt", "❌", f"Błąd: {str(e)[:30]}")) #### 3. Usuwanie testowego artykułu############## try: response = requests.delete( f"{self.base_url}/delete-article", json={"title": article_to_save["title"]}, timeout=5 ) operations.append(("Usuwanie", "✅" if response.status_code == 200 else "⚠️", f"Status: {response.status_code}")) except Exception as e: operations.append(("Usuwanie", "SKIP", f"Błąd: {str(e)[:30]}")) details = " | ".join([f"{op[0]}: {op[1]} ({op[2]})" for op in operations]) success_ops = sum(1 for op in operations if op[1] in ["✅", "SKIP"]) status = "PASS" if success_ops >= 2 else "FAIL" self.log_test(test_name, status, details) return operations except Exception as e: self.log_test(test_name, "FAIL", f"Błąd ogólny: {str(e)}") return None ##################### Generuje raport tekstowy z porównaniem ########## def generate_text_report(self, filename: str = "truthscan_report.txt"): total_tests = len(self.results) passed = sum(1 for r in self.results if r["status"] == "PASS") report = f""" {'='*80} RAPORT PORÓWNAWCZY TRUTHSCAN AI - BBC vs GAZETA PRAWNA {'='*80} Data wykonania: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} Backend URL: {self.base_url} Frontend URL: {self.frontend_url} {'='*80} PODSUMOWANIE TESTOW: {'='*80} Wszystkie testy: {total_tests} Przepuszczone: {passed} Nieudane: {sum(1 for r in self.results if r["status"] == "FAIL")} Ostrzeżenia: {sum(1 for r in self.results if r["status"] == "WARNING")} Wskaźnik sukcesu: {passed/total_tests*100:.1f}% {'='*80} WYNIKI PORÓWNANIA: {'='*80} """ if self.comparison_data: report += f""" BBC: • Artykułów: {self.comparison_data['source_count']['BBC']} • Średnie fake_probability: {self.comparison_data['avg_fake_score']['BBC']:.2f}% • Czas odpowiedzi: {self.comparison_data['performance']['BBC']:.2f}s • Rozkład sentymentu: {json.dumps(self.comparison_data['sentiment_distribution']['BBC'], ensure_ascii=False)} Gazeta Prawna: • Artykułów: {self.comparison_data['source_count']['Gazeta Prawna']} • Średnie fake_probability: {self.comparison_data['avg_fake_score']['Gazeta Prawna']:.2f}% • Czas odpowiedzi: {self.comparison_data['performance']['Gazeta Prawna']:.2f}s • Rozkład sentymentu: {json.dumps(self.comparison_data['sentiment_distribution']['Gazeta Prawna'], ensure_ascii=False)} ANALIZA RÓŻNIC: • Różnica w fake_probability: {abs(self.comparison_data['avg_fake_score']['BBC'] - self.comparison_data['avg_fake_score']['Gazeta Prawna']):.2f}% • Różnica w czasie odpowiedzi: {abs(self.comparison_data['performance']['BBC'] - self.comparison_data['performance']['Gazeta Prawna']):.2f}s """ report += f""" {'='*80} WYNIKI SZCZEGÓŁOWE: {'='*80} """ for result in self.results: status_icon = "✅" if result["status"] == "PASS" else "❌" if result["status"] == "FAIL" else "⚠️" duration = f"[{result['duration']:.2f}s]" if result["duration"] else "" report += f"{status_icon} {result['test_name']} {duration}\n" report += f" {result['details']}\n" report += f" Czas: {result['timestamp'][11:19]}\n\n" # Przykładowe artykuły if self.bbc_results.get("sample_titles") or self.gazeta_results.get("sample_titles"): report += f""" {'='*80} PRZYKŁADOWE ARTYKUŁY: {'='*80} """ if self.bbc_results.get("sample_titles"): report += "BBC:\n" for i, title in enumerate(self.bbc_results["sample_titles"][:3]): report += f" {i+1}. {title}\n" if self.gazeta_results.get("sample_titles"): report += "\nGazeta Prawna:\n" for i, title in enumerate(self.gazeta_results["sample_titles"][:3]): report += f" {i+1}. {title}\n" report += f""" {'='*80} WNIOSKI I REKOMENDACJE: {'='*80} 1. System {'działa poprawnie' if passed > total_tests/2 else 'wymaga poprawy'} 2. Obsługa języka polskiego: {'SPRAWNIE' if self.gazeta_results.get('articles') else 'PROBLEMY'} 3. Średni czas odpowiedzi: {statistics.mean([r['duration'] for r in self.results if r.get('duration')]):.2f}s 4. Główne problemy: {len(self.errors)} błędów 5. Gotowość do dalszych testów: {'TAK' if len(self.errors) < 3 else 'NIE'} REKOMENDACJE: 1. {'Naprawić wykryte błędy' if self.errors else 'Wszystko działa poprawnie'} 2. Przeprowadzić testy manualne interfejsu 3. Przetestować więcej źródeł RSS 4. Sprawdzić działanie na różnych przeglądarkach 5. {'Wymagany fine-tuning modeli dla języka polskiego' if self.comparison_data and abs(self.comparison_data['avg_fake_score']['BBC'] - self.comparison_data['avg_fake_score']['Gazeta Prawna']) > 15 else 'Modele działają spójnie dla obu języków'} """ with open(filename, 'w', encoding='utf-8') as f: f.write(report) print(f"📝 Raport tekstowy zapisany jako: {filename}") return report """Generuje szczegółowy raport HTML z porównaniem źródeł""" def generate_comparative_html_report(self, filename: str = "truthscan_report.html"): total_tests = len(self.results) passed = sum(1 for r in self.results if r["status"] == "PASS") # Przygotowanie danych do wykresów if self.comparison_data: sources = ["BBC", "Gazeta Prawna"] fake_scores = [ self.comparison_data['avg_fake_score']['BBC'], self.comparison_data['avg_fake_score']['Gazeta Prawna'] ] performance_times = [ self.comparison_data['performance']['BBC'], self.comparison_data['performance']['Gazeta Prawna'] ] # Dane sentymentu bbc_sentiments = self.comparison_data['sentiment_distribution']['BBC'] gazeta_sentiments = self.comparison_data['sentiment_distribution']['Gazeta Prawna'] # Przygotowanie etykiet i wartości dla wykresów sentymentu bbc_sentiment_labels = list(bbc_sentiments.keys()) if bbc_sentiments else ['Neutralny', 'Pozytywny', 'Negatywny'] bbc_sentiment_values = list(bbc_sentiments.values()) if bbc_sentiments else [1, 1, 1] gazeta_sentiment_labels = list(gazeta_sentiments.keys()) if gazeta_sentiments else ['Neutralny', 'Pozytywny', 'Negatywny'] gazeta_sentiment_values = list(gazeta_sentiments.values()) if gazeta_sentiments else [1, 1, 1] else: sources = ["BBC", "Gazeta Prawna"] fake_scores = [0, 0] performance_times = [0, 0] bbc_sentiment_labels = ['Neutralny', 'Pozytywny', 'Negatywny'] bbc_sentiment_values = [1, 1, 1] gazeta_sentiment_labels = ['Neutralny', 'Pozytywny', 'Negatywny'] gazeta_sentiment_values = [1, 1, 1] html = f""" Raport porównawczy TruthScan AI - BBC vs Gazeta Prawna

📊 RAPORT PORÓWNAWCZY TRUTHSCAN AI

BBC vs Gazeta Prawna - Analiza systemu detekcji dezinformacji

Data testów: {datetime.now().strftime('%d.%m.%Y %H:%M:%S')}

BBC

Artykułów: {self.comparison_data.get('source_count', {}).get('BBC', 0)}

Fake: {fake_scores[0]:.1f}%

Czas: {performance_times[0]:.2f}s

Gazeta Prawna

Artykułów: {self.comparison_data.get('source_count', {}).get('Gazeta Prawna', 0)}

Fake: {fake_scores[1]:.1f}%

Czas: {performance_times[1]:.2f}s

📈 Średnie ryzyko dezinformacji

⚡ Wydajność systemu

🎭 Rozkład sentymentu - BBC

🎭 Rozkład sentymentu - Gazeta Prawna

🔍 Kluczowe różnice:

• Różnica w ryzyku dezinformacji: {abs(fake_scores[0] - fake_scores[1]):.1f}%

• Różnica w czasie analizy: {abs(performance_times[0] - performance_times[1]):.2f}s

{"

• ⚠️ Znacząca różnica w wykrywaniu dezinformacji między językami

" if abs(fake_scores[0] - fake_scores[1]) > 10 else "

• ✅ Spójna skuteczność detekcji między językami

"}

📰 Przykładowe artykuły z analizą

BBC:
""" #### Przykładowe artykuły BBC if self.bbc_results.get("sample_titles"): for i, title in enumerate(self.bbc_results["sample_titles"][:2]): html += f"

{i+1}. {title}...

" else: html += "

Brak przykładowych artykułów

" html += """
Gazeta Prawna:
""" #### Przykładowe artykuły Gazeta Prawna if self.gazeta_results.get("sample_titles"): for i, title in enumerate(self.gazeta_results["sample_titles"][:2]): html += f"

{i+1}. {title}...

" else: html += "

Brak przykładowych artykułów

" html += f"""

📋 Wyniki testów ({passed}/{total_tests} przepuszczonych)

""" for result in self.results: status_class = "pass" if result["status"] == "PASS" else "fail" if result["status"] == "FAIL" else "warn" status_display = {"PASS": "✅", "FAIL": "❌", "WARNING": "⚠️"}.get(result["status"], "?") duration = f"{result['duration']:.2f}" if result["duration"] else "-" html += f""" """ html += f"""
Test Status Szczegóły Czas [s]
{result['test_name']} {status_display} {result['status']} {result['details']} {duration}

Wnioski i rekomendacje

Kluczowe wnioski:
Rekomendacje:
  1. Fine-tuning modeli NLP na polskich danych fact-checkingowych
  2. Optymalizacja parsowania polskich znaków diakrytycznych
  3. Implementacja cache'owania wyników dla często analizowanych źródeł
  4. Rozszerzenie testów o więcej polskich źródeł informacji
  5. Przeprowadzenie testów z rzeczywistymi użytkownikami
""" with open(filename, 'w', encoding='utf-8') as f: f.write(html) print(f"\n📄 Raport porównawczy HTML zapisany jako: {filename}") print(f" Otwórz w przeglądarce: file://{os.path.abspath(filename)}") return filename def run_comparative_tests(self): """Uruchamia pełne testy porównawcze""" print("=" * 70) print("🎯 TRUTHSCAN AI - TESTY PORÓWNAWCZE BBC vs GAZETA PRAWNA") print("=" * 70) print("Ten skrypt przeprowadzi szczegółowe testy obu źródeł") print("i porówna ich wyniki analizy NLP.") print("=" * 70) # Sprawdzenie dostępności API print("\n1️⃣ Sprawdzanie dostępności systemu...") if not self.test_api_availability(): print("❌ API niedostępne! Sprawdź czy backend działa.") return False # Test źródeł print("\n2️⃣ Weryfikacja dostępnych źródeł...") sources = self.test_sources_endpoint() if not sources: print("⚠️ Nie udało się pobrać źródeł, używam domyślnych...") sources = ["BBC", "GazetaPrawna"] else: print(f"✅ Znaleziono {len(sources)} źródeł") # Test BBC print("\n3️⃣ Testowanie źródła BBC...") self.bbc_results = self.test_single_source_detailed("BBC", "BBC News") # Test Gazety Prawnej print("\n4️⃣ Testowanie źródła Gazeta Prawna...") self.gazeta_results = self.test_single_source_detailed("GazetaPrawna", "Gazeta Prawna") # Porównanie wyników if self.bbc_results.get("articles") and self.gazeta_results.get("articles"): print("\n5️⃣ Porównywanie wyników BBC i Gazety Prawnej...") self.compare_sources(self.bbc_results, self.gazeta_results) else: print("⚠️ Brak danych do porównania") # Testy CRUD dla obu źródeł print("\n6️⃣ Testy operacji na danych...") self.test_crud_operations_for_source("BBC") self.test_crud_operations_for_source("GazetaPrawna") # Generowanie raportów print("\n" + "=" * 70) print("📊 GENEROWANIE RAPORTÓW") print("=" * 70) html_report = self.generate_comparative_html_report() text_report = self.generate_text_report() # Podsumowanie passed = sum(1 for r in self.results if r["status"] == "PASS") total = len(self.results) print(f"\n{'='*70}") print(f"📋 PODSUMOWANIE TESTOW:") print(f" Przepuszczono: {passed}/{total} ({passed/total*100:.1f}%)") if self.errors: print(f" Błędy: {len(self.errors)}") if self.comparison_data: fake_diff = abs(self.comparison_data['avg_fake_score']['BBC'] - self.comparison_data['avg_fake_score']['Gazeta Prawna']) time_diff = abs(self.comparison_data['performance']['BBC'] - self.comparison_data['performance']['Gazeta Prawna']) print(f"\n🔍 WNIOSKI Z PORÓWNANIA:") print(f" • Różnica w ryzyku dezinformacji: {fake_diff:.1f}%") print(f" • Różnica w czasie analizy: {time_diff:.2f}s") if fake_diff > 10: print(f" • ⚠️ Znacząca różnica w NLP między językami") if time_diff > 2: print(f" • ⏱️ Analiza polskiego języka wymaga więcej czasu") print(f"\n📁 Raporty wygenerowane:") print(f" HTML: {html_report}") print(f" Tekst: {text_report}") print(f"{'='*70}") return passed > total * 0.7 def main(): """Główna funkcja""" print("🎯 TruthScan AI - Testy porównawcze BBC vs Gazeta Prawna") print("=" * 70) tester = TruthScanComparativeTester() # Uruchom testy success = tester.run_comparative_tests() print("\n" + "=" * 70) if success: print("✅ TESTY ZAKOŃCZONE SUKCESEM!") else: print("⚠️ TESTY WYKAZAŁY PROBLEMY - sprawdź raport") print("=" * 70) print("\n📋 Otwórz raport HTML w przeglądarce:") print(f" file://{os.path.abspath('truthscan_comparative_report.html')}") return success if __name__ == "__main__": try: import requests except ImportError: print("❌ Brak biblioteki 'requests'") print("💡 Zainstaluj: pip install requests") exit(1) main()