Сквозное тестирование веб-сервисов - PullRequest
1 голос
/ 01 мая 2009

Первый постер и TDD усыновитель. :-) Я буду немного многословен, поэтому, пожалуйста, потерпите меня.

Недавно я начал разработку веб-сервисов на основе SOAP с использованием инфраструктуры Apache CXF, Spring и Commons Chain для реализации бизнес-процессов. Проблема, с которой я здесь сталкиваюсь, заключается в тестировании веб-сервисов - тестировании как в модульном тестировании, так и в функциональном тестировании.

Моя первая попытка модульного тестирования была полным провалом. Чтобы обеспечить гибкость модульных тестов, я использовал файл Spring XML для хранения своих тестовых данных. Кроме того, вместо создания экземпляров «компонентов» для тестирования, я извлек их из контекста моего Spring-приложения. XML-файлы, содержащие данные, быстро вышли из-под контроля; создание графов объектов в XML оказалось кошмаром. Поскольку «компоненты», подлежащие тестированию, были выбраны из контекста приложения Spring, при каждом запуске теста загружалось все компоненты, используемые в моем приложении, используемые объекты DAO и т. Д. Кроме того, в отличие от концепции модульного теста когда дела были централизованы или сконцентрированы на тестировании только компонента, мои модульные тесты начали попадать в базы данных, общаться с почтовыми серверами и т. д. Плохо, очень плохо.

Я знал, что я сделал неправильно, и начал думать о том, как исправить это. Следуя совету одного из постов на этой доске, я посмотрел Mockito, фреймворк для Java-моделирования, чтобы я мог покончить с использованием реальных классов DAO и почтовых серверов и просто высмеивать их функциональность.

С юнит-тестами немного под контролем, это подводит меня ко второй проблеме; зависимость от данных. Веб-сервисы, которые я разрабатывал, имеют очень мало логики, но сильно зависят от данных. В качестве примера рассмотрим один из моих компонентов:

public class PaymentScheduleRetrievalComponent implements Command {
  public boolean execute(Context ctx) {
    Policy policy = (Policy)ctx.get("POLICY");
    List<PaymentSchedule> list = billingDAO.getPaymentStatementForPolicy(policy);
    ctx.put("PAYMENT_SCHEDULE_LIST", list);
    return false;
  }
}

Большинство моих компонентов следуют по одному и тому же маршруту - выберите объект домена из контекста, нажмите DAO [мы используем iBatis в качестве средства отображения SQL здесь] и получите результат.

Итак, теперь вопросы:
- Как классы DAO тестируются esp, когда одна вставка или обновление могут оставить базу данных в «нестабильном» состоянии [в случаях, когда, скажем, 3 вставки в разные таблицы фактически образуют одну транзакцию]?
- Что является стандартом де-факто для функционального тестирования веб-сервисов, которые перемещают много данных, то есть бессмысленных вставок / извлечений из хранилища данных?

Ваш личный опыт / комментарии будут с благодарностью. Пожалуйста, дайте мне знать, если я пропустил некоторые детали с моей стороны, объясняя проблему.

-sasuke

Ответы [ 5 ]

2 голосов
/ 05 мая 2009

Я бы держался подальше от шаблона "Context as global hashmap" на вашем месте.

Похоже, вы проверяете свое постоянное отображение ...

Возможно, вы захотите взглянуть на: тестирование постоянных объектов без пружины

1 голос
/ 29 апреля 2014

Прежде всего, проясните ситуацию.

В идеальном мире жизненный цикл создаваемого вами программного обеспечения выглядит примерно так: - sy делает отчет с клиентом, поэтому вы получаете пользовательскую историю с примерами того, как должно работать приложение - вы обобщаете пользовательскую историю, поэтому у вас есть правила, которые вы называете вариантами использования - вы начинаете писать часть функционального (сквозного) теста, и он не проходит ... - после этого вы создаете пользовательский интерфейс и макетируете сервисы, чтобы вы получили зеленый функциональный тест и спецификацию о том, как ваши сервисы должны работать ... - ваша задача - поддерживать функциональный тест зеленым и реализовывать сервисы, шаг за шагом писать интеграционные тесты и выстраивать зависимости таким же образом, пока вы не достигнете уровня модульных тестов - после этого вы выполняете следующую итерацию со сценариями использования, пишете следующий фрагмент функционального теста и так далее до конца проекта - после этого вы проводите приемочные испытания с клиентом, который принимает товар и платит много

Итак, что мы узнали из этого:

  • Есть много типов тестов (не путайте их друг с другом)
    • функциональные тесты - для тестирования вариантов использования (ничего не копировать)
    • интеграционные тесты - для тестирования взаимодействия приложений, компонентов, модулей, классов (макетирование нерелевантных компонентов)
    • модульные тесты - для тестирования одного класса изолированно от его среды (макетируйте все)
    • пользовательские приемочные тесты - клиент удостоверяется, что он принимает продукт (ручные функциональные тесты или презентация, сделанная из автоматических функциональных тестов в работе)
  • Вам не нужно проверять все с помощью функциональных и интеграционных тестов, потому что это невозможно. Протестируйте только соответствующую часть с помощью функциональных и интеграционных тестов и протестируйте все с помощью модульных тестов! Ознакомьтесь с испытательной пирамидой .
  • Используйте TDD, это облегчает жизнь!
  • Как тестируются классы DAO, особенно если одна вставка или обновление могут оставить базу данных в «нестабильном» состоянии [в случаях, когда скажем, 3 вставки в разные таблицы на самом деле образуют единый сделка]

Вам не нужно проверять транзакции базы данных. Предположим, что они работают хорошо, потому что разработчики баз данных уже проверили их, и я уверен, что вы не хотите писать тесты параллелизма ... Db - это внешний компонент, поэтому вам не нужно тестировать его самостоятельно. Вы можете написать слой доступа к данным, чтобы адаптировать хранилище данных к вашей системе, и написать интеграционные тесты только для этих адаптеров. В случае миграции базы данных эти тесты также будут работать адаптерами новой базы данных, потому что вы пишете их для реализации определенного интерфейса ... С помощью любых других тестов (кроме функциональных тестов) вы можете смоделировать уровень доступа к данным. Сделайте то же самое с любым другим внешним компонентом, напишите адаптеры и макетируйте их. Поместите такого рода интеграционные тесты в набор тестов, отличный от других тестов, потому что они медленные из-за доступа к базе данных, доступа к файловой системе и т. Д. *

  • Что является стандартом де-факто для функциональных веб-сервисов тестирования, которые перемещаются вокруг большого количества данных, то есть бессмысленных вставок / извлечений из хранилища данных?

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

1 голос
/ 08 мая 2009

Я бы порекомендовал базу данных в памяти для выполнения ваших модульных тестов, таких как HSQL. Вы можете использовать это для создания вашей схемы на лету (например, если вы используете Hibernate, вы можете использовать файлы сопоставлений XML), затем вставьте / обновите / удалите, как требуется, перед уничтожением базы данных в конце вашего модульного теста. Ваш тест ни при каких условиях не будет влиять на вашу реальную базу данных.

Для вас вторая проблема (сквозное тестирование веб-сервисов), в прошлом я успешно тестировал сервисы на основе CXF. Хитрость заключается в том, чтобы публиковать ваш веб-сервис с использованием облегченного веб-сервера в начале теста (Jetty идеален), затем использовать CXF, чтобы указать клиенту на конечную точку вашего веб-сервиса, выполнить ваши вызовы, а затем, наконец, завершить работу Jetty. экземпляр хостинга вашего веб-сервиса после завершения юнит-теста.

Для достижения этого вы можете использовать классы JaxWsServerFactoryBean (на стороне сервера) и JaxWsProxyFactoryBean (на стороне клиента), предоставляемые с CXF, см. Эту страницу для примера кода:

http://cwiki.apache.org/CXF20DOC/a-simple-jax-ws-service.html#AsimpleJAX-WSservice-Publishingyourservice

Я также хотел бы поблагодарить SOAP UI за функциональное тестирование вашего веб-сервиса. JMeter также чрезвычайно полезен для стресс-тестирования веб-сервисов, что особенно важно для тех сервисов, которые выполняют поиск в базе данных.

1 голос
/ 04 мая 2009

Прежде всего: есть ли причина, по которой вам нужно получить тестируемый объект (SUT) из контекста приложения Spring? Для эффективного модульного тестирования вы должны иметь возможность создавать SUT без контекста. Похоже, у вас где-то есть скрытые зависимости. Это может быть причиной вашей головной боли.

Как тестируются классы DAO, особенно если одиночная вставка или обновление может оставить базу в «нестабильном» состояние [в тех случаях, когда, скажем, 3 вставки в разные таблицы на самом деле сформировать одну транзакцию]?

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

  1. Отметьте все ваши фальшивые данные с помощью некоторого общего идентификатора, например, добавив специальный префикс в поле.
  2. Перед запуском теста удалите оператор удаления, который удаляет помеченные данные. Если его нет, то ничего плохого не происходит.
  3. Запустите тест DAO. После этого повторите шаг 2. для следующего теста.

Что является стандартом де-факто для функциональное тестирование веб-сервисов, которые перемещать много данных, т.е. бессмысленные вставки / извлечения из хранилище данных?

Я не знаю ни о чем. Из вопроса, который вы задаете, я могу заключить, что у вас есть веб-сервис с одной стороны, а с другой - база данных. Разделите обязанности. Есть отдельные наборы тестов для каждой стороны. Одна сторона просто тестирует доступ к базе данных (как описано выше). С другой стороны, просто тестирование запросов и ответов веб-сервисов. В этом случае он платит за заглушку / фальшивку / издевательство над уровнем, разговаривающим с сетью. Или рассмотрим https://wsunit.dev.java.net/.

Если программа только загружает и отправляет данные, я думаю, что это не так много. Если это так, то самая сложная работа состоит в модульном тестировании стороны базы данных и стороны веб-службы. Дело в том, что вы можете проводить модульное тестирование без «реалистичных» данных. Для функционального тестирования вам понадобятся данные, обработанные вручную, что близко к реальности. Это может быть громоздким, но если вы уже интенсивно тестировали компоненты базы данных и веб-службы, это должно значительно снизить потребность в «реалистичных» тестовых случаях.

0 голосов
/ 04 мая 2009

Должен сказать, я не очень понимаю ваша точная проблема. Проблема что ваша база данных оставлена ​​в измененное состояние после запуска проверить

Да, на самом деле здесь есть две проблемы. Во-первых, проблема с базой данных, оставшейся в несогласованном состоянии после выполнения тестовых случаев. Во-вторых, я ищу элегантное решение с точки зрения комплексного тестирования веб-сервисов.

Для эффективного модульного тестирования вы должны быть в состоянии создать SUT без контекст. Похоже, у вас есть некоторые где-то скрытые зависимости Тот может быть корнем некоторых из ваших головная боль.

Это действительно было основной причиной моей головной боли, которую я сейчас собираюсь устранить с помощью насмешливых рамок.

Кажется, вы беспокоитесь о постоянство базы данных после того, как у вас есть запуск тестов. Если возможно, используйте собственная база данных для тестирования, где вы не нужно заботиться об этом. Если у вас есть такую ​​базу данных песочницы вы можете удалить данные, как вы хотите.

Это действительно одно из решений проблемы, о которой я говорил в предыдущем посте, но это может не сработать во всех случаях, особенно при интеграции с устаревшей системой, в которой база данных / данные не находятся под вашим контролем, а в случаях когда некоторые методы DAO требуют, чтобы определенные данные уже присутствовали в данном наборе таблиц. Должен ли я посмотреть на основы модульного тестирования базы данных, такие как DBUnit?

В этом случае он платит заглушка / фейк / издеваться над слоем сеть. Или посмотрим https://wsunit.dev.java.net/.

Ах, выглядит интересно. Я также слышал о таких инструментах, как SOAPUI и подобных, которые можно использовать для функционального тестирования. Кто-нибудь здесь имел успех с такими инструментами?

Спасибо за все ответы и извинения за неоднозначное объяснение; Английский не мой родной язык.

-sasuke

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...