Нужно ли еще больше тестировать разработанный искусственным интеллектом код?

Необходимо ли проводить дополнительное тестирование кода, разработанного искусственным интеллектом?

Инструменты на основе искусственного интеллекта для написания кода, такие как GitHub Copilot, становятся все популярнее в разработке программного обеспечения. Эти инструменты обещают повысить производительность, но некоторые также утверждают, что они демократизируют программирование, позволяя непрограммистам писать приложения. 

Но как мы на самом деле знаем, подходит ли код, написанный с помощью инструмента ИИ?

В следующем вы узнаете, что означает “подходящий для назначения” и какие инструменты вы можете использовать для его оценки. Мы увидим, что инструменты на основе ИИ для написания кода не могут гарантировать ничего в отношении функциональной корректности и безопасности предлагаемого ими кода. Однако мы также увидим, что на самом деле есть инструменты ИИ, которые могут помочь вам ответить на указанный выше вопрос.

Возвращаемся в прошлое

Стоит начать с небольшой исторической отсрочки, потому что этот вопрос нам не знаком вовсе: мы всегда должны были себе задавать вопрос: “Как мы на самом деле знаем, что код, написанный людьми, соответствует назначению?” Люди десятилетиями ломали голову, пытаясь найти решения этой фундаментальной проблемы в программной инженерии.

С самых ранних дней программных компьютерных систем инженеры получали неприятные сюрпризы, когда программы не делали то, что они задумывали. Тогда количество циклов проб и ошибок, чтобы получить правильные программы, было очень дорогим. Низкоуровневый код нужно было разрабатывать вручную и вбивать в карты. Основной контрмерой против лишних циклов был кодовый обзор. Кодовый обзор означает, что эксперт читает и пытается понять, что делает код, чтобы обнаружить ошибки и давать рекомендации по улучшению – успешная методика, которую по-прежнему широко практикуют сегодня. Однако эффективность обзоров и усилия для их тщательного проведения снижаются, а затраты растут с увеличением размера и сложности программ.

Скоро возник вопрос о том, как на самом деле узнать более строгим образом, делает ли программа то, что она должна делать. Проблема в том, как выразить то, что программа должна делать. Каким-то образом это должно быть передано машине, что именно хочет пользователь. Эта задача представляет собой чрезвычайно сложную проблему, которая до сих пор не полностью решена сегодня.

Проблема является общей для инженерии продукта во всех областях и разделяется на два шага, которые обычно формулируются в виде вопросов: 

  1. Мы создали правильный продукт?
  2. Мы создали продукт правильно?

Валидация и верификация

Оценка того, был ли создан правильный продукт, известна как валидация. В конечном счете пользователи проверяют, соответствует ли продукт его назначению. Верификация исходит из технического задания, которое служит средством коммуникации между создателями продукта и пользователем или заказчиком. Спецификации должны пониматься обеими сторонами: пользователем (экспертом в области) и инженером (который может не быть экспертом в области). Верификация состоит в оценке того, соответствует ли реализация продукта требованиям технического задания. Валидация является более сложной проблемой. Что является «правильным» продуктом, является субъективным и трудно автоматизировать.

Хорошей новостью является то, что часть проверки может быть полностью автоматизирована: в принципе, до вычислительных и сложностных пределов. Просто говоря, можно математически доказать, что реализация соответствует требованиям технического задания. Эта дисциплина известна как формальные методы или формальная верификация и основана на логических формализмах для написания спецификаций и автоматизированного рассуждения для выполнения доказательств.

Как многообещающе это звучит, главной проблемой остается то, кто пишет спецификации. Для этого требуется человек, являющийся экспертом в этой области и специалистом в написании формальных спецификаций – таких людей найти сложно и очень дорого. Даже когда вы нашли такого человека и смогли проверить вашу реализацию, вы все равно остаетесь с проблемой валидации; то есть, соответствует ли спецификация действительно описанию правильного продукта с точки зрения пользователя.

Часто отмечается, что спецификации часто «более неверны», чем реализация, потому что экстремально сложно правильно формулировать формальные спецификации. Огромная проблема остается в масштабировании автоматизированного рассуждения на большие системы. На практике формальная верификация нашла свое место для сравнительно маленьких, сложных и критически важных (безопасность, безопасность, финансовое) программных продуктов от встроенного управления, криптографии и ядер операционных систем до умных контрактов.

Другой взгляд на вещи

В 1970-х годах появилась другая идея решить проблему с другой стороны, называемая многократное программирование. Основная идея заключается в том, что поскольку так сложно правильно составить программы и даже их спецификации, позволяется нескольким независимым командам реализовывать систему, а затем голосовать за результат. Предполагается, что разные команды делают разные ошибки, у них также могут быть разные интерпретации требований технического задания. Таким образом, в целом, результат ожидается «более правильным», чем одна реализация с точки зрения верификации и, возможно, даже валидации. Однако выяснилось, что предположение было неверным: последующие исследования показали, что даже независимые команды делают те же ошибки.

Одним из наследий этого подхода является то, что проверку можно рассматривать как программирование с двумя версиями: спецификация требований и реализация представляют собой две стороны одной и той же монеты. Они описывают одну и ту же систему по-разному, используя разные формализмы и точки зрения. Кроме того, их часто пишут разные люди или команды. Ни спецификация, ни реализация “более правильные” не являются, и наоборот. Такой подход позволяет нам реалистично оценить, что может быть достигнуто на практике.

Итак, зачем нам нужны и спецификации, и реализации? Выгода заключается в программировании с двумя версиями: сравнение двух описаний одной и той же системы позволяет нам быть уверенными в согласованности и отыскать ошибки в случае расхождений, позволяя нам пересмотреть оба описания и в конечном итоге получить “более правильные” описания.

Тестирование – это техника верификации

Теперь некоторые читатели могут возражать: у нас нет спецификаций, поэтому мы не можем это сделать. Как это нас касается? У вас может не быть четкой спецификации требований, но вы можете проводить тестирование вашего программного обеспечения. Правда, мы еще не говорили о тестировании. Что на самом деле делает тестирование в контексте нашего обсуждения?

Тестирование – это техника верификации. Тесты проверяют вашу реализацию, и утверждения в ваших тестах – это, как вы уже догадались, спецификация. Как часто происходило так, что ошибка была не в реализации, а в тестах? Это неудивительно, поскольку тестирование – это всего лишь программирование с двумя версиями. Поэтому хорошая практика тестирования с использованием тестов на всех уровнях действительно увеличивает уверенность в доставке правильного продукта. А что насчет модельно-ориентированной инженерии? Да, это такая же техника программирования с двумя версиями с теми же свойствами.

Так что нам нужно больше тестировать код, написанный ИИ?

Оценить, насколько приложение, созданное инструментом ИИ, подходит для целей, так же сложно, как оценить человеком написанный код – хотя инструменты генерации кода с использованием ИИ обязательно требуют обзора разработчиком. Сложной частью является ответ на вопрос о валидации: человек, делающий эту оценку, должен быть экспертом в области приложений.

Инструмент для автоматического написания тестов помогает вам в этом процессе, поскольку созданные им тесты дают вам поведенческое представление ввода-вывода кода. Например, я являюсь соавтором автоматизированного решения для написания тестов под названием Diffblue Cover. Он не делает догадок – он прямо говорит вам, что код на самом деле делает и таким образом помогает вам оценить вопросы валидации и верификации. Тесты служат в качестве базового материала для регрессионного тестирования при внесении изменений в код в будущем – независимо от того, был ли он написан человеком или машиной.

Шансы довольно хороши, что не программисты, но эксперты в своей области применения могут воспользоваться инструментами ИИ для программирования приложений. Однако им нужно осознавать, что реализации, созданные инструментами, такими как GitHub Copilot, не являются строительными – функциональная корректность и безопасность не встроены в используемые ими базовые модели. Даже если они обучены на “правильном” коде (мы сейчас знаем, насколько это мало значит, так как ни один предприятийный разработчик не поместит в производство код, сгенерированный ИИ, не предварительно тщательно его проверив) и безопасном коде, эти свойства не сохраняются в процессе обучения и оценки моделей.

ИИ для спасения ИИ

Инструменты, работающие на основе ИИ, позволяют легко создавать приложения, выполняющие определенные действия. Однако код приложения должен ожидать тех же проблем, что и код, написанный человеком. Поэтому вам необходимо использовать ту же строгость при тестировании и контроле качества, что и для кода, написанного человеком. Доверие к этим процессам может быть увеличено совместно с инструментом ИИ для автоматического написания тестов, который может гарантировать, что создаваемые им тесты описывают фактическое поведение кода.