{"meta":{"title":"Schreiben von Tests mit GitHub Copilot","intro":"Verwende Copilot, um Komponenten- und Integrationstests zu generieren und zu einer besseren Codequalität beizutragen.","product":"GitHub Copilot","breadcrumbs":[{"href":"/de/copilot","title":"GitHub Copilot"},{"href":"/de/copilot/tutorials","title":"Anleitungen"},{"href":"/de/copilot/tutorials/write-tests","title":"Tests schreiben"}],"documentType":"article"},"body":"# Schreiben von Tests mit GitHub Copilot\n\nVerwende Copilot, um Komponenten- und Integrationstests zu generieren und zu einer besseren Codequalität beizutragen.\n\n## Einführung\n\nGitHub Copilot kann dir helfen, Tests schneller zu entwickeln und die Produktivität zu verbessern. In diesem Artikel wird veranschaulicht, wie du mit Copilot Komponenten- und Integrationstests schreibst. Während sich Copilot besonders zum Generieren von Tests für grundlegende Funktionen eignet, erfordern komplexe Szenarios detailliertere Prompts und Strategien. Dieser Artikel enthält praktische Beispiele dafür, wie mit Copilot Aufgaben aufgeschlüsselt und die Codekorrektheit überprüft werden kann.\n\n## Voraussetzungen\n\nBevor Sie beginnen, müssen Sie Folgendes haben:\n\n* Ein [GitHub Copilot-Abonnementplan](/de/copilot/about-github-copilot/subscription-plans-for-github-copilot).\n* Visual Studio, Visual Studio Code oder eine beliebige JetBrains-IDE\n* Die [GitHub Copilot Erweiterung](/de/copilot/managing-copilot/configure-personal-settings/installing-the-github-copilot-extension-in-your-environment) ist in Ihrer IDE installiert.\n\n## Unit-Tests mit Copilot-Chat\n\nschreiben\n\nIn diesem Abschnitt erfährst du, wie du mit GitHub Copilot Chat Komponententests für eine Python-Klasse generierst. In diesem Beispiel wird veranschaulicht, wie du mit Copilot Komponententests für eine Klasse wie `BankAccount` erstellst. Außerdem erfährst du, wie du Copilot aufforderst, Tests zu generieren, diese auszuführen und die Ergebnisse zu überprüfen.\n\n### Beispielklasse: `BankAccount`\n\nAngenommen, du hast eine Klasse `BankAccount`, die Methoden zum Einzahlen, Auszahlen und Abrufen des Kontostands enthält. Erstellen Sie eine neue Datei `bank_account.py` in einem GitHub Repository, und fügen Sie die folgende `BankAccount`-Klasse in Python hinzu.\n\n```python\nclass BankAccount:\n    def __init__(self, initial_balance=0):\n        if initial_balance < 0:\n            raise ValueError(\"Initial balance cannot be negative.\")\n        self.balance = initial_balance\n\n    def deposit(self, amount):\n        if amount <= 0:\n            raise ValueError(\"Deposit amount must be positive.\")\n        self.balance += amount\n\n    def withdraw(self, amount):\n        if amount <= 0:\n            raise ValueError(\"Withdrawal amount must be positive.\")\n        if amount > self.balance:\n            raise ValueError(\"Cannot withdraw more than the current balance.\")\n        self.balance -= amount\n\n    def get_balance(self):\n        return self.balance\n```\n\n### Unit-Tests mit Copilot-Chat\n\ngenerieren\n\nDu kannst Copilot dazu auffordern, Tests zu schreiben, die verschiedene Szenarios abdecken. Achte auf spezifische Testanforderungen, um die besten Ergebnisse zu erzielen. Im Folgenden findest du einen Beispielprompt, mit dem du Komponententests für die `BankAccount`-Klasse generieren kannst.\n\n```\n          **Prompt:**_„Schreibe eine umfassende Sammlung von Komponententests für die BankAccount()-Funktion in Python. Schreibe mehrere Testmethoden, die viele verschiedene Szenarios abdecken, einschließlich Grenzfällen, Ausnahmebehandlung und Datenüberprüfung.“_\n```\n\nWichtige Aspekte dieses Prompts:\n\\*\n**Geltungsbereich:** Er fragt explizit nach einer umfassenden Sammlung von Komponententests, damit Copilot mehr als nur grundlegende Tests generiert und viele verschiedene potenzielle Anwendungsfälle abdeckt.\n\\*\n**Szenarios:** Der Prompt gibt an, dass die Tests Folgendes berücksichtigen sollen:\n\\*\n**Grenzfälle**: Es wird auf Grenzbedingungen (z. B. negative Werte für Ein- oder Auszahlungen und Auszahlungen, die den verfügbaren Saldo übersteigen) getestet.\n\\*\n**Ausnahmebehandlung:** Es wird auf Fehler getestet, die ausgelöst werden sollen, wenn bestimmte ungültige Aktionen auftreten (z. B. Auszahlungen, die den verfügbaren Saldo übersteigen und das Einzahlen negativer Beträge).\n\\*\n**Datenüberprüfung:** Es wird sichergestellt, dass Eingaben von den Methoden korrekt validiert und verarbeitet werden.\n\nDie Antwort von Copilot wird der folgenden ähneln.\n\n```python\nimport unittest\nfrom bank_account import BankAccount\n\nclass TestBankAccount(unittest.TestCase):\n    def setUp(self):\n        self.account = BankAccount()\n\n    def test_initial_balance(self):\n        self.assertEqual(self.account.get_balance(), 0)\n\n    def test_deposit_positive_amount(self):\n        self.account.deposit(100)\n        self.assertEqual(self.account.get_balance(), 100)\n\n    def test_withdraw_within_balance(self):\n        self.account.deposit(100)\n        self.account.withdraw(50)\n        self.assertEqual(self.account.get_balance(), 50)\n\n    def test_deposit_negative_amount_raises_error(self):\n        with self.assertRaises(ValueError):\n            self.account.deposit(-100)\n\n    def test_withdraw_negative_amount_raises_error(self):\n        with self.assertRaises(ValueError):\n            self.account.withdraw(-50)\n\n    def test_withdraw_more_than_balance_raises_error(self):\n        self.account.deposit(100)\n        with self.assertRaises(ValueError):\n            self.account.withdraw(200)\n\n    def test_initial_balance_negative_raises_error(self):\n        with self.assertRaises(ValueError):\n            BankAccount(-100)\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\n### Ausführen der Testfälle\n\nDie von Copilot generierte Testsammlung enthält einen Testfall für jedes Szenario, das im Prompt angegeben ist. Jede Funktion in der `BankAccount`-Klasse wird auf verschiedene Bedingungen getestet, einschließlich gültiger Vorgänge wie Ein- und Auszahlungen sowie Grenzfälle wie negative Beträge und versuchte Auszahlungen, die den verfügbaren Saldo übersteigen.\n\nNachdem Copilot die Testsammlung zu deiner Zufriedenheit generiert hat, füge den Code in eine neue `test_bank_account.py`-Datei ein. Du kannst fragen, wie die Tests ausgeführt werden.\n\n```\n          **Prompt:**_\"Wie führe ich diese Unit-Tests in Python mit dem unittest-Framework aus?\"_\n```\n\nCopilot gibt dir den folgenden Bash-Befehl zurück.\n\n```bash\npython -m unittest test_bank_account.py\n```\n\nNach dem Ausführen der Tests wird dir die Ausgabe im Terminal oder in der IDE angezeigt. Wenn alle Tests erfolgreich abgeschlossen werden, kannst du sicher sein, dass deine `BankAccount`-Klasse erwartungsgemäß funktioniert.\n\n#### Slash-Befehl\n\nDarüber hinaus kannst du Copilot auffordern, eine vollständige Sammlung von Komponententests mit dem Slash-Befehl `/tests` zu schreiben. Stelle sicher, dass die Datei in der aktuellen Registerkarte deiner IDE geöffnet ist, und Copilot wird Komponententests für diese Datei generieren. Die Tests, die Copilot generiert, decken unter Umständen nicht alle Szenarios ab. Daher solltest du den generierten Code immer überprüfen und zusätzliche Tests hinzufügen, die ggf. erforderlich sind.\n\n> \\[!TIP] Wenn du Copilot bittest, Tests für eine Codedatei zu schreiben, die nicht von Komponententests abgedeckt wird, kannst du nützlichen Kontext für Copilot bereitstellen, indem du mindestens eine bestehende Testdatei in benachbarten Registerkarten in deinem Editor öffnest. Copilot erkennt das verwendete Testframework und kann mit größerer Wahrscheinlichkeit einen Test schreiben, der zu deinen bestehenden Tests passt.\n\nCopilot generiert eine Komponententestsammlung wie die folgende.\n\n```python\nimport unittest\nfrom bank_account import BankAccount\n\nclass TestBankAccount(unittest.TestCase):\n    def setUp(self):\n        self.account = BankAccount()\n\n    def test_initial_balance(self):\n        self.assertEqual(self.account.get_balance(), 0)\n```\n\n## Schreiben von Integrationstests mit Copilot\n\nIntegrationstests sind unerlässlich, um sicherzustellen, dass die verschiedenen Komponenten deines Systems zusammen ordnungsgemäß funktionieren. In diesem Abschnitt wird die `BankAccount`-Klasse um Interaktionen mit einem externen Dienst `NotificationSystem` erweitert. Außerdem wird Systemverhalten mit Modelltests getestet, ohne dass echte Verbindungen erforderlich sind. Ziel der Integrationstests ist es, die Interaktion zwischen der `BankAccount`-Klasse und den `NotificationSystem`-Diensten zu prüfen und sicherzustellen, dass sie ordnungsgemäß zusammenarbeiten.\n\n### Beispielklasse: `BankAccount` mit Benachrichtigungsdiensten\n\nAktualisiere die `BankAccount`-Klasse, sodass Interaktionen mit einem externen Dienst einbezogen werden, z. B. ein `NotificationSystem`-Dienst, der Benachrichtigungen an Benutzer sendet.\n`NotificationSystem` stellt die Integration dar, die getestet werden muss.\n\nAktualisiere die `BankAccount`-Klasse in der `bank_account.py`-Datei mit dem folgenden Codeschnipsel.\n\n```python\nclass BankAccount:\n    def __init__(self, initial_balance=0, notification_system=None):\n        if initial_balance < 0:\n            raise ValueError(\"Initial balance cannot be negative.\")\n        self.balance = initial_balance\n        self.notification_system = notification_system\n\n    def deposit(self, amount):\n        if amount <= 0:\n            raise ValueError(\"Deposit amount must be positive.\")\n        self.balance += amount\n        if self.notification_system:\n            self.notification_system.notify(f\"Deposited {amount}, new balance: {self.balance}\")\n\n    def withdraw(self, amount):\n        if amount <= 0:\n            raise ValueError(\"Withdrawal amount must be positive.\")\n        if amount > self.balance:\n            raise ValueError(\"Cannot withdraw more than the current balance.\")\n        self.balance -= amount\n\n        if self.notification_system:\n            self.notification_system.notify(f\"Withdrew {amount}, new balance: {self.balance}\")\n\n    def get_balance(self):\n        return self.balance\n```\n\nIn diesem Fall sollte die Anforderung für Copilot, Integrationstests für die `BankAccount`-Klasse zu schreiben, in kleinere, besser handhabbare Einheiten aufgeteilt werden. So kann Copilot genauere und relevantere Tests generieren.\n\n```\n          **Prompt:**_„Schreibe Integrationstests für die `deposit`-Funktion in der `BankAccount`-Klasse. Verwende Modelltests, um `NotificationSystem` zu simulieren und zu überprüfen, ob der Dienst nach einer Einzahlung richtig aufgerufen wird.“_\n```\n\nWichtige Aspekte dieses Prompts:\n\\*\n**Geltungsbereich:** Es spezifiziert Integrationstests, die sich auf die Interaktion zwischen der `deposit`-Funktion und `NotificationSystem` konzentrieren, anstelle von nur Einheitstests.\n\\*\n**Modelltests:** Er fordert explizit die Verwendung von Modelltests, um `NotificationSystem` zu simulieren und sicherzustellen, dass die Interaktion mit externen Systemen getestet wird, ohne dass diese tatsächlich implementiert werden müssen.\n\\*\n**Überprüfung:** Der Prompt fordert, dass das korrekte Aufrufen der `NotificationSystem`-Funktion nach einer Einzahlung überprüft werden muss, um sicherzustellen, dass die Integration zwischen den Komponenten erwartungsgemäß funktioniert.\n\\*\n**Genauigkeit:** Der Prompt gibt die zu testende Methode (`deposit`) und die zu testende Klasse (`BankAccount`) genau vor.\n\n> \\[!TIP] Wenn Copilot ungültige Tests erzeugt, stelle Beispiele für Ein- und Ausgaben der Funktion bereit, die du testen möchtest. Dies wird Copilot dabei helfen, das erwartete Verhalten der Funktion zu bewerten.\n\nCopilot generiert eine Testsammlung wie die folgende.\n\n```python\nimport unittest\nfrom unittest.mock import Mock\nfrom bank_account import BankAccount\n\nclass TestBankAccountIntegration(unittest.TestCase):\n    def setUp(self):\n        self.notification_system = Mock()\n\n    def test_deposit_with_notification(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        account.deposit(50)\n        self.assertEqual(account.get_balance(), 150)\n        self.notification_system.notify.assert_called_once_with(\"Deposited 50, new balance: 150\")\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\nFüge den generierten Code in eine neue `test_bank_account_integration.py`-Datei ein.\n\n### Verbessern der Testfälle\n\nDer oben genannte Prompt hat einen einzigen Testfall generiert, der überprüft, ob `NotificationSystem` nach einer gültigen Einzahlung aufgerufen wird. Jedoch deckt es keine Fälle ab, in denen während der Einzahlung ein Fehler ausgelöst wird. In diesen Szenarios sollte `NotificationSystem` nicht aufgerufen werden. Daher sollte ein Testfall hinzugefügt werden, der ungültige Einzahlungen verarbeitet und sicherstellt, dass das Benachrichtigungssystem nicht ausgelöst wird.\n\n```\n          **Prompt:**_„Füge einen Testfall für ungültige Einzahlungsbeträge hinzu, um sicherzustellen, dass die Funktion die richtigen Ausnahmen auslöst und dass `NotificationService` nicht aufgerufen wird.“_\n```\n\nCopilot generiert einen Testfall wie den folgenden.\n\n```python\n    def test_deposit_negative_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.deposit(0)\n        self.notification_system.notify.assert_not_called()\n```\n\n### Fragen zu Verbesserungspotenzialen\n\nDa wir nun Testfälle geschrieben haben, um die Integrationsfunktionalität für Einzahlungen zu überprüfen, ist dies eine großartige Gelegenheit, nach Verbesserungen innerhalb der Testreihe zu suchen. Auch wenn die aktuellen Tests ihren Zweck erfüllen, kannst du Copilot auffordern, die Code Coverage zu testen und Verbesserungen vorzuschlagen.\n\n```\n          **Prompt:**_„Welche zusätzlichen Tests sollten einbezogen werden, um die Integration zwischen der `BankAccount`-Klasse und `NotificationSystem` vollständig abzudecken?“_\n```\n\nCopilot diese Frage zu stellen, kann dir helfen, fehlende Testfälle zu ermitteln, die möglicherweise übersehen wurden.\nIm vorliegenden Beispiel wurden zwar gültige und ungültige Einzahlungen getestet, jedoch nicht die Auszahlungsfunktion.\n\nCopilot generiert eine aktualisierte Testsammlung wie die folgende.\n\n<details>\n  <summary>Klicke hier, um das vollständige generierte Codebeispiel anzuzeigen.</summary>\n\n```python\nimport unittest\nfrom unittest.mock import Mock\nfrom bank_account import BankAccount\n\nclass TestBankAccountIntegration(unittest.TestCase):\n    def setUp(self):\n        self.notification_system = Mock()\n\n    def test_deposit_with_notification(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        account.deposit(50)\n        self.assertEqual(account.get_balance(), 150)\n        self.notification_system.notify.assert_called_once_with(\"Deposited 50, new balance: 150\")\n\n    def test_deposit_negative_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.deposit(-50)\n        self.notification_system.notify.assert_not_called()\n\n    def test_deposit_zero_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.deposit(0)\n        self.notification_system.notify.assert_not_called()\n\n    def test_withdraw_with_notification(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        account.withdraw(30)\n        self.assertEqual(account.get_balance(), 70)\n        self.notification_system.notify.assert_called_once_with(\"Withdrew 30, new balance: 70\")\n\n    def test_withdraw_exceeding_balance_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.withdraw(150)\n        self.notification_system.notify.assert_not_called()\n\n    def test_withdraw_negative_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.withdraw(-30)\n        self.notification_system.notify.assert_not_called()\n\n    def test_withdraw_zero_amount_raises_error(self):\n        account = BankAccount(initial_balance=100, notification_system=self.notification_system)\n        with self.assertRaises(ValueError):\n            account.withdraw(0)\n        self.notification_system.notify.assert_not_called()\n\n    def test_initial_negative_balance_raises_error(self):\n        with self.assertRaises(ValueError):\n            BankAccount(initial_balance=-100, notification_system=self.notification_system)\n\nif __name__ == '__main__':\n    unittest.main()\n```\n\n</details>\n\nWenn du mit der von Copilot generierten Testsammlung zufrieden bist, führe die Tests mit dem folgenden Befehl aus, um die Ergebnisse zu überprüfen.\n\n```bash\npython -m unittest test_bank_account_integration.py\n```\n\n## Verwenden von Copilot Räume zur Verbesserung von Testvorschlägen\n\nCopilot Räume ist ein Feature, mit dem du aufgabenspezifischen Kontext mit Copilot organisieren und freigeben kannst. Dies kann dazu beitragen, die Relevanz der erhaltenen Vorschläge zu verbessern. Indem Sie Copilot mit mehr Kontext zu Ihrem Projekt versehen, können Sie bessere Testvorschläge erhalten.\n\nDu kannst z. B. einen Raum erstellen, der Folgendes umfasst:\n\n* Das Modul, das du testest (z. B. `payments.js`)\n* Die aktuelle Testsuite (z. B. `payments.test.js`)\n* Ein Testabdeckungsbericht oder Hinweise zu fehlenden Aspekten\n\nIm Raum kannst du Copilot Fragen stellen, z. B.:\n\n> Welche Testfälle fehlen in `payments.test.js` basierend auf der Logik in `payments.js`?\n\nOder:\n\n> Schreibe einen Komponententest für die Erstattungslogik in `refund.js`, nach der Struktur in der vorhandenen Testsuite.\n\nWeitere Informationen findest du unter Copilot Räume, siehe [Über GitHub Copilot Spaces](/de/copilot/using-github-copilot/copilot-spaces/about-organizing-and-sharing-context-with-copilot-spaces)."}