Введение
GitHub Copilot помогает быстро разрабатывать тесты и повысить производительность. В этой статье мы покажем, как использовать Copilot для записи модульных и интеграции тестов. Хотя Copilot хорошо работает при создании тестов для базовых функций, сложные сценарии требуют более подробных запросов и стратегий. В этой статье рассматриваются практические примеры использования Copilot для разбиения задач и проверки правильности кода.
Необходимые компоненты
Прежде чем getting started, у вас должны быть следующее:
- A GitHub Copilot подписочный план.
- Visual Studio, Visual Studio Codeили любой интегрированной среды разработки JetBrains.
- Расширение GitHub Copilot установлено в вашем IDE.
Написание модульных тестов с помощью Copilot Chat
В этом разделе мы рассмотрим, как использовать GitHub Copilot Чат для создания модульных тестов для класса Python. В этом примере показано, как использовать Copilot для создания модульных тестов для класса, например BankAccount. Мы покажем, как запрашивать Copilot создавать тесты, выполнять их и проверять результаты.
Пример класса: BankAccount
Начнем с класса BankAccount , содержащего методы для депозита, вывода и получения баланса учетной записи. Создайте новый файл bank_account.py в репозитории GitHub и добавьте следующий класс BankAccount на Python.
class BankAccount:
def __init__(self, initial_balance=0):
if initial_balance < 0:
raise ValueError("Initial balance cannot be negative.")
self.balance = initial_balance
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit amount must be positive.")
self.balance += amount
def withdraw(self, amount):
if amount <= 0:
raise ValueError("Withdrawal amount must be positive.")
if amount > self.balance:
raise ValueError("Cannot withdraw more than the current balance.")
self.balance -= amount
def get_balance(self):
return self.balance
Создание модульных тестов с помощью Copilot Chat
Вы можете запросить Copilot с запросом на запись тестов, охватывающих ряд сценариев. Будьте конкретными с требованиями к тесту, чтобы получить наилучшие результаты. Ниже приведен пример запроса, который можно использовать для создания модульных BankAccount тестов для класса.
**Запрос.**_Разработка комплексного набора модульных тестов для функции BankAccount() в Python. Создание нескольких методов тестирования, охватывающих широкий спектр сценариев, включая пограничные случаи, обработку исключений и проверку данных._
В этом запросе выполняется несколько важных действий. * Область: явно запрашивает полный набор модульных тестов, поэтому Copilot создает более чем простые тесты, охватывающие различные потенциальные варианты использования. * Сценарии: запрос указывает, что тесты должны включать: * Пограничные случаи: тесты для условий границ (например, отрицательные значения для депозитов или вывода, вывод больше, чем доступный баланс). * Обработка исключений: тесты на наличие ошибок, которые должны возникать при возникновении определенных недопустимых действий (например, отменяя больше, чем доступный баланс, вкладывание отрицательных сумм). * Проверка данных. Убедитесь, что входные данные правильно проверяются и обрабатываются методами.
Copilot даст ответ, как показано ниже.
import unittest
from bank_account import BankAccount
class TestBankAccount(unittest.TestCase):
def setUp(self):
self.account = BankAccount()
def test_initial_balance(self):
self.assertEqual(self.account.get_balance(), 0)
def test_deposit_positive_amount(self):
self.account.deposit(100)
self.assertEqual(self.account.get_balance(), 100)
def test_withdraw_within_balance(self):
self.account.deposit(100)
self.account.withdraw(50)
self.assertEqual(self.account.get_balance(), 50)
def test_deposit_negative_amount_raises_error(self):
with self.assertRaises(ValueError):
self.account.deposit(-100)
def test_withdraw_negative_amount_raises_error(self):
with self.assertRaises(ValueError):
self.account.withdraw(-50)
def test_withdraw_more_than_balance_raises_error(self):
self.account.deposit(100)
with self.assertRaises(ValueError):
self.account.withdraw(200)
def test_initial_balance_negative_raises_error(self):
with self.assertRaises(ValueError):
BankAccount(-100)
if __name__ == '__main__':
unittest.main()
Выполнение тестов
Набор тестов, созданный Copilot, включает тестовый случай для каждого сценария, указанного в запросе. Каждая функция в BankAccount классе проверяется для ряда условий, включая допустимые операции, такие как депозиты и вывод, а также пограничные случаи, такие как отрицательные суммы и попытки снять больше, чем доступный баланс.
После создания набора тестов Copilot добавьте код в новый файл test_bank_account.py. Вы можете спросить его, как выполнить тесты.
**Prompt:**_"How do I запускать эти модульные тесты на Python с использованием фреймворка unittest?"_
Copilot предоставит следующую команду Bash.
python -m unittest test_bank_account.py
После выполнения тестов вы увидите выходные данные в терминале или интегрированной среде разработки. Если все тесты проходят, вы можете быть уверены, что ваш BankAccount класс работает должным образом.
Команда с косой чертой
Кроме того, можно заставить Copilot написать полный набор модульных тестов с помощью команды косой /tests черты. Убедитесь, что файл открыт на текущей вкладке интегрированной среды разработки и Copilot создаст модульные тесты для этого файла. Тесты, создаваемые Copilot, могут не охватывать все сценарии, поэтому всегда следует просматривать созданный код и добавлять любые дополнительные тесты, которые могут потребоваться.
Совет
Если вы попросите Copilot написать тесты для файла кода, который еще не охвачен модульными тестами, можно предоставить Copilot с полезным контекстом, открыв один или несколько существующих файлов тестов на смежных вкладках в редакторе. Copilot сможет увидеть используемую платформу тестирования и будет более вероятно написать тест, соответствующий существующим тестам.
Copilot создаст набор модульных тестов, например следующий.
import unittest
from bank_account import BankAccount
class TestBankAccount(unittest.TestCase):
def setUp(self):
self.account = BankAccount()
def test_initial_balance(self):
self.assertEqual(self.account.get_balance(), 0)
Написание тестов интеграции с помощью Copilot
Тесты интеграции необходимы для обеспечения правильной работы различных компонентов системы при объединении. В этом разделе мы расширим наш BankAccount класс, чтобы включить взаимодействие с внешней службой NotificationSystem и использовать макеты для тестирования поведения системы без необходимости реальных подключений. Цель тестов интеграции заключается в проверке взаимодействия между классом BankAccount и NotificationSystem службами, обеспечивая правильную работу вместе.
Пример класса: BankAccount с службами уведомлений
Давайте обновим BankAccount класс, чтобы включить взаимодействие с внешней службой, например NotificationSystem , которая отправляет уведомления пользователям.
NotificationSystem представляет интеграцию, которую необходимо протестировать.
`BankAccount` Обновите класс в файле с помощью следующего `bank_account.py` фрагмента кода.
class BankAccount:
def __init__(self, initial_balance=0, notification_system=None):
if initial_balance < 0:
raise ValueError("Initial balance cannot be negative.")
self.balance = initial_balance
self.notification_system = notification_system
def deposit(self, amount):
if amount <= 0:
raise ValueError("Deposit amount must be positive.")
self.balance += amount
if self.notification_system:
self.notification_system.notify(f"Deposited {amount}, new balance: {self.balance}")
def withdraw(self, amount):
if amount <= 0:
raise ValueError("Withdrawal amount must be positive.")
if amount > self.balance:
raise ValueError("Cannot withdraw more than the current balance.")
self.balance -= amount
if self.notification_system:
self.notification_system.notify(f"Withdrew {amount}, new balance: {self.balance}")
def get_balance(self):
return self.balance
Здесь мы разберем наш запрос на Copilot для записи тестов интеграции для BankAccount класса в меньшие, более управляемые части. Это поможет Copilot создавать более точные и соответствующие тесты.
**Запрос:**_"Написание тестов интеграции для функции в `deposit` классе. Используйте макеты для `BankAccount` имитации `NotificationSystem` и проверки правильности вызова после депозита"._
В этом запросе выполняется несколько важных действий.
*
Область. Он задает тесты интеграции, фокусируя внимание на взаимодействии между deposit функцией и NotificationSystemфункцией, а не только модульными тестами.
*
Макеты: явно запрашивает использование макетов для имитации NotificationSystem, гарантируя, что взаимодействие с внешними системами проверяется, не полагаясь на их фактическую реализацию.
*
Проверка: запрос подчеркивает правильность NotificationSystem вызова после депозита, гарантируя, что интеграция между компонентами работает должным образом.
*
Специфика. Запрос четко указывает метод (deposit) и класс (BankAccount) для проверки.
Совет
Если Copilot создает недопустимые тесты, укажите примеры входных и выходных данных для функции, которую требуется протестировать. Это поможет Copilot оценить ожидаемое поведение функции.
Copilot создаст набор тестов, как показано ниже.
import unittest
from unittest.mock import Mock
from bank_account import BankAccount
class TestBankAccountIntegration(unittest.TestCase):
def setUp(self):
self.notification_system = Mock()
def test_deposit_with_notification(self):
account = BankAccount(initial_balance=100, notification_system=self.notification_system)
account.deposit(50)
self.assertEqual(account.get_balance(), 150)
self.notification_system.notify.assert_called_once_with("Deposited 50, new balance: 150")
if __name__ == '__main__':
unittest.main()
Добавьте созданный код в новый файл test_bank_account_integration.py.
Улучшение тестовых вариантов
Приведенный выше запрос создал один тестовый случай, который проверяет NotificationSystem , вызывается при внесении допустимого депозита. Однако он не охватывает случаи, когда во время депозита возникает ошибка. В этих сценариях NotificationSystem не следует вызывать. Необходимо добавить тестовый случай, обрабатывающий недопустимые депозиты, и убедиться, что система уведомлений не активируется.
**Запрос:**_"Добавьте тестовый случай для недопустимых сумм депозита, чтобы убедиться, что функция вызывает правильные исключения и не `NotificationService` вызывается"._
Copilot создаст тестовый случай, например следующий.
def test_deposit_negative_amount_raises_error(self):
account = BankAccount(initial_balance=100, notification_system=self.notification_system)
with self.assertRaises(ValueError):
account.deposit(0)
self.notification_system.notify.assert_not_called()
Вопрос о областях улучшения
Теперь, когда мы написали тестовые случаи для проверки функциональности интеграции для депозитов, это отличная возможность для поиска улучшений в наборе тестов. Хотя текущие тесты являются функциональными, мы можем предложить Copilot оценить охват кода и предложить области улучшения.
**Запрос:**_"Какие дополнительные тесты следует включить, чтобы обеспечить полное покрытие интеграции между классом `BankAccount` и `NotificationSystem`?"_
Запрос Copilot с этим вопросом может помочь определить отсутствующие тестовые случаи, которые, возможно, были пропущены. В этой ситуации, пока мы проверили действительные и недопустимые депозиты, мы еще не рассмотрели функциональные возможности вывода.
Copilot создаст обновленный набор тестов, например следующий.
Щелкните, чтобы развернуть полный пример созданного кода
import unittest
from unittest.mock import Mock
from bank_account import BankAccount
class TestBankAccountIntegration(unittest.TestCase):
def setUp(self):
self.notification_system = Mock()
def test_deposit_with_notification(self):
account = BankAccount(initial_balance=100, notification_system=self.notification_system)
account.deposit(50)
self.assertEqual(account.get_balance(), 150)
self.notification_system.notify.assert_called_once_with("Deposited 50, new balance: 150")
def test_deposit_negative_amount_raises_error(self):
account = BankAccount(initial_balance=100, notification_system=self.notification_system)
with self.assertRaises(ValueError):
account.deposit(-50)
self.notification_system.notify.assert_not_called()
def test_deposit_zero_amount_raises_error(self):
account = BankAccount(initial_balance=100, notification_system=self.notification_system)
with self.assertRaises(ValueError):
account.deposit(0)
self.notification_system.notify.assert_not_called()
def test_withdraw_with_notification(self):
account = BankAccount(initial_balance=100, notification_system=self.notification_system)
account.withdraw(30)
self.assertEqual(account.get_balance(), 70)
self.notification_system.notify.assert_called_once_with("Withdrew 30, new balance: 70")
def test_withdraw_exceeding_balance_raises_error(self):
account = BankAccount(initial_balance=100, notification_system=self.notification_system)
with self.assertRaises(ValueError):
account.withdraw(150)
self.notification_system.notify.assert_not_called()
def test_withdraw_negative_amount_raises_error(self):
account = BankAccount(initial_balance=100, notification_system=self.notification_system)
with self.assertRaises(ValueError):
account.withdraw(-30)
self.notification_system.notify.assert_not_called()
def test_withdraw_zero_amount_raises_error(self):
account = BankAccount(initial_balance=100, notification_system=self.notification_system)
with self.assertRaises(ValueError):
account.withdraw(0)
self.notification_system.notify.assert_not_called()
def test_initial_negative_balance_raises_error(self):
with self.assertRaises(ValueError):
BankAccount(initial_balance=-100, notification_system=self.notification_system)
if __name__ == '__main__':
unittest.main()
После того как Copilot создал набор тестов для удовлетворения, выполните тесты с помощью команды ниже, чтобы проверить результаты.
python -m unittest test_bank_account_integration.py
Использование Copilot Spaces для улучшения вариантов тестирования
Copilot Spaces — это функция, которая позволяет упорядочивать и предоставлять общий доступ к контексту для конкретной задачи с помощью Copilot. Это поможет улучшить релевантность получаемых предложений. Предоставив Copilot больше контекста о вашем project, вы сможете получить лучшие рекомендации по тестированию.
Например, можно создать пространство, включающее:
- Модуль, который вы тестируете (например
payments.js) - Текущий набор тестов (например
payments.test.js) - Отчет о охвате теста или заметки о том, что отсутствует
В пространстве можно задать такие вопросы, как Copilot:
Какие тестовые случаи отсутствуют на
payments.test.jsоснове логики вpayments.js?
Или сделайте так:
Напишите модульный тест для логики
refund.jsвозврата, следуя структуре в существующем наборе тестов.
Для получения дополнительной информации об использовании Copilot Spaces см. О GitHub Copilot Spaces.