Автоматизация контрольных тестов приложений бизнес-процессов на Java при помощи IBM Business Process Manager

REST API, предоставляемый IBM® Business Process Manager, позволяет выполнять бизнес-процесс от начала до конца. В статье эта возможность используется совместно с Java™ REST Client API для написания автоматизированных контрольных тестов на Java с помощью JUnit и DBUnit. Из журнала IBM Business Process Management Journal.

Хорхе Рафаэль Ногерас, программист-консультант, IBM

Хорхе Рафаэль Ногерас (Jorge Rafael Nogueras) – фотографияХорхе Рафаэль Ногерас (Jorge Rafael Nogueras) - инженер-программист в IBM Software Group, разработчик в группе IBM Business Process Manager. Свою карьеру в IBM он начал в качестве разработчика ядра в подразделении AIX TCP/IP группы System and Technology, а затем перешел в группу Systems Management, где занимался разработкой компонента WPAR Manager для системы IBM Systems Director. Рафаэль получил степень бакалавра в области вычислительной техники в университете Пуэрто-Рико (кампус Маягес) и степень магистра в области компьютерных наук в Массачусетском технологическом институте.



Рикардо Оливьери, разработчик, IBM

Рикардо Оливьери (Ricardo Olivieri) является разработчиком программного обеспечения в команде IBM Global Services. Он специализируется в проектировании и разработке корпоративных Java-систем под сервер приложений WebSphere, его администрировании и конфигурировании, а также в архитектурах распределенных приложений. В последние несколько лет Рикардо заинтересовался проектами с открытым кодом, такими как Drools, Spring, WebWork, Hibernate и JasperReports. Он является сертифицированным Java-разработчиком и администратором сервера приложений WebSphere. Кроме того, он окончил университет Пуэрто-Рико в Маягуэсе с дипломом бакалавра по специальности «вычислительная техника».



11.10.2013

Введение

REST API, предоставляемый IBM® Business Process Manager, позволяет выполнять бизнес-процесс от начала до конца. В статье эта возможность используется совместно с Java™ REST Client API, представленным в статье Интеграция приложений бизнес-процессов в IBM Business Process Manager версий V7.5.1 и V8 с внешней системой с помощью REST API для написания автоматизированных контрольных тестов на Java с помощью JUnit и DBUnit (EN).

Примечание редактора. Файл download.zip был обновлен.

Предположения

Чтобы понять темы, обсуждаемые в статье, читатель должен быть знаком с основными функциями IBM Business Process Manager и общими концепциями разработки приложений бизнес-процессов. Предполагается знание Java, JEE, JUnit, DBUnit, Spring, JavaScript, WebSphere Application Server (включая настройку источников данных), систем безопасности Web-приложений, архитектуры передачи репрезентативного состояния (REST), интегрированных сред разработки (например, Eclipse), языков программирования в целом и автоматизации тестирования ПО. Если у вас нет опыта написания автоматизированных контрольных тестов на Java, рекомендуем познакомиться с JUnit и DBUnit до прочтения данной статьи.


Причины использования методик автоматизированного модульного тестирования

Нередко в IBM Business Process Manager (IBM BPM) выполняется несколько SQL-запросов к одной или нескольким базам данных для сбора данных на различных этапах выполнения бизнес-процесса. Например, диаграмма бизнес-процесса (business process design – BPD) начинается с получения сообщения, а затем по мере выполнения процесс обращается к нескольким таблицам базы данных и применяет к данным бизнес-правила и бизнес-логику "на лету". Кроме того, бизнес-процессы часто многократно обновляют базу данных в конце выполнения.

С помощью JUnit и DBUnit можно писать интегрированные контрольные тесты, автоматически заполняющие таблицы базы данных необходимыми для процесса данными и проверяющие утверждения в различных точках бизнес-процесса. Таким образом можно написать тестовый код, гарантирующий, что данные изменены "на лету" надлежащим образом, что люди выполнили правильные действия и что по завершении бизнес-процесса база данных содержит ожидаемые значения.

Пример процесса BPD и Java-кода, использующего JUnit и DBUnit для управления выполнением бизнес-процесса и его и тестированием, приведен в разделе Загрузка.


Библиотека Java REST API

В предыдущей статье Интеграция приложений бизнес-процессов в IBM Business Process Manager версий V7.5.1 и V8 с внешней системой с помощью REST API (EN) на developerWorks обсуждалась интеграция внешних Java-приложений с бизнес-процессами, созданными в IBM BPM. В ней были представлены повторно используемые Java-активы и библиотеки, обеспечивающие полную интеграцию Java-приложений и процессов в IBM BPM посредством REST-вызовов. В данной статье мы будем опираться на знания, полученные при изучении предыдущей статьи. Мы используем упомянутые выше Java-активы для написания с помощью JUnit и DBUnit контрольных тестов интеграции для бизнес-процессов в IBM BPM. Заметьте, мы не говорим, что использование JUnit и DBUnit является единственным способом тестирования приложений бизнес-процессов в IBM BPM. Можно выполнять тестирование вручную или использовать другой подход к тестированию в зависимости от сложности требований процесса в IBM BPM. Цель данной статьи – познакомить с одним из возможных подходов и методик, которые можно использовать для тестирования процессов в IBM BPM.


Модель тестовых данных

Начнем со знакомства с моделью данных базы данных, используемой в примере бизнес-процесса, который мы собираемся обсудить. На рисунке 1 показаны таблицы базы данных и их отношения.

Рисунок 1. Модель данных
Рисунок 1. Модель данных

Как показано на рисунке 1, модель данных состоит из объекта request (запрос), который связан только с одним объектом account (учетная запись). Обратите внимание, что каждый объект account связан с одним объектом account_category (категория учетной записи), а каждый объект request связан с одним объектом request_type (тип запроса).

Продолжим описание примера бизнес-процесса (назовем пример Sample BPD). Как показано на рисунке 2, в Sample BPD выполняются 5 действий: три действия выполняет система, а 2 действия выполняет человек. На рисунке 3 показано определение переменных для примера бизнес-процесса. Обратите внимание, что одна входная переменная, requestId, имеет тип Integer, а одна частная переменная, request, имеет тип Request (это сложный тип, определенный для данного приложения процесса). Прежде чем продолжить чтение, вам следует познакомиться с переменными и их типами.

Рисунок 2. Диаграмма BPD для примера Sample BPD
Рисунок 2. Диаграмма BPD для примера Sample BPD
Рисунок 3. Определение переменных для примера Sample BPD
Рисунок 3. Определение переменных для примера Sample BPD

Теперь рассмотрим различные действия в Sample BPD. Чтобы запустить бизнес-процесс, необходимо в качестве входного значения предоставить идентификатор запроса. Без этого значения процесс не пойдет и выдаст ошибку. Первым действием процесса является Get Request, в котором используется переменная requestID для выполнения SQL-запроса к базе данных. Используя данные, полученные из базы данных для соответствующего значения requestID, первое действие возвращает заполненный объект Request.

После действия Get Request следует шлюз Account Category, оценивающий категорию учетной записи, указанной в переменной request. Затем в зависимости от значения категории выполняется одно из трех действий (на рисунке 4 показано определение шлюза), приведенных в таблице 1.

Таблица 1. Запрос категорий и связанные с ним действия
КатегорияДействие
Very Important Account – очень важная учетная записьApprove (Automated) – одобрение (автоматическое)
Important Account – важная учетная записьFull Review – полная проверка
Not So Important Account – обычная учетная запись (по умолчанию)Quick Review – быстрая проверка

Рисунок 4. Определение шлюза Account Category
Рисунок 4. Определение шлюза Account Category

Давайте рассмотрим каждое действие. Как показано на рисунке 5, действие Approve (Automated) одобряет запрос (без вмешательства человека) и заполняет поле комментариев.

Рисунок 5. Реализация действия Approve (Automated)
Рисунок 5. Реализация действия Approve (Automated)

Действие Full Review выполняется человеком – пользователь Checker проверяет данные объекта request. Кроме того, Checker может использовать другие системы (например, используя подход swivel chair – поворотное кресло) и вводить свои выводы в поле комментариев. В зависимости от своих выводов пользователь Checker одобряет или отклоняет запрос.

Действие Quick Review выполняется человеком – пользователь Reviewer проверяет данные объекта request. Пользователь Reviewer выполняет беглую проверку данных запроса и решает, отклонить запрос или одобрить. Одобренный пользователем Reviewer запрос направляется пользователю Checker для тщательной проверки.

После принятия окончательного решения (одобрен или отклонен) относительно входящего запроса выполняется действие Update Status. На рисунке 6 показана реализация этого действия.

Рисунок 6. Реализация сервиса Update Status
Рисунок 6. Реализация сервиса Update Status

Обратите внимание, что сервис Update Status должен вызывать фиктивный Web-сервис (для получения значения системного кода), только если типом запроса является Type 1. Во всех остальных случаях вызов фиктивного Web-сервиса не выполняется и значение полю systemCode значение не присваивается. Как показано на рисунке 7, реализация вызова фиктивного Web-сервиса присваивает полю systemCode жестко закодированное значение.

Рисунок 7. Реализация вызова фиктивного Web-сервиса
Рисунок 7. Реализация вызова фиктивного Web-сервисаcall

Сервис Update Status обновляет состояние запроса в базе данных, сохраняя следующие поля объекта request:

  • comments – комментарии пользователя (или системы в случае автоматического одобрения), проверившего запрос.
  • approved – окончательное решение относительно запроса.
  • systemCode – значение, возвращенное фиктивным Web-сервисом, который вызывается для всех запросов типа Type 1.

Тестирование

После анализа процесса в IBM BPM и внесения изменений в его реализацию бизнес-процесс можно протестировать. Чтобы протестировать пример Sample BPD (данные в тестовой базе данных можно настраивать вручную перед выполнением каждого теста), используйте Process Designer для выполнения бизнес-процесса, а также перспективу Inspector для анализа хода процесса и значений данных на каждом шаге, выполняемом человеком. Как только процесс завершится, можно вручную выполнить SQL-запросы для проверки данных в таблицах базы данных. Эти шаги выполняются вручную каждый раз для каждого контрольного теста.

Альтернативой описанному выше подходу к тестированию является написание Java-кода для IBM BPM с использованием JUnit, DBUnit и Java REST-клиента с целью автоматизации тестирования. Использование автоматизированных тестов значительно улучшает качество результатов работы в IBM BPM и требует меньше времени, чем выполнение каждого теста вручную. Рассмотрим пример, который показывает, как это сделать.

JUnit-класс примера теста для процесса Sample BPD имеет имя SampleBPDProcessTests. В листинге 1 приведена реализация метода setUpClass() класса SampleBPDProcessTests. Обратите внимание, что этот метод аннотирован JUnit-аннотацией @BeforeClass. Он создает экземпляр класса BPMClientImpl, используя учетные данные IBM BPM и информацию о доступе, содержащуюся в файле sampleBPMProps.txt (см. листинг 2). В зависимости от плана тестов можно создать собственный экземпляр класса BPMClientImpl для каждого выполнения теста. Например, при выполнении каждого метода теста с разными учетными данными пользователя IBM BPM нужны разные экземпляры класса BPMClientImpl для каждого теста. В этом примере мы используем один и тот же экземпляр во всех тестах, так как его достаточно для целей нашего тестирования (кроме того, при повторном использовании одного экземпляра объекта повышается скорость работы).

Листинг 1. Реализация метода setUpClass()
   @BeforeClass
   public static void setUpClass() throws Exception {
      BPMAccess bpmAccess = new BPMAccess(
            "/sample/process/tests/sampleBPMProps.txt");
      WASAuthenticationTokenHandler handler = new WASAuthenticationTokenHandler(
            bpmAccess.getUser(), bpmAccess.getPassword());
      bpmClient = new BPMClientImpl(bpmAccess.getHostname(),
            bpmAccess.getPort(), handler);
      utils = new TestUtils(bpmClient);
   }
Листинг 2. Содержимое файла свойств sampleBPMProps.txt
# Имя хоста центра/сервера процесса
hostname=localhost

# Номер порта центра/сервера процесса
port=9080

# Идентификатор пользователя BPM для подключения к центру/серверу процесса
user=tw_admin

# Пароль пользователя BPM для подключения к центру/серверу процесса
password=admin

В листинге 3 приведена реализация методов getSeedFilesMetaData() и getDBAaccess(). Они вызываются методом, аннотированным JUnit-аннотацией @Before. Эти методы указывают информацию о доступе к базе данных и учетные данные для подключения к базе данных (см. листинг 4), а также данные (см. листинг 5), которые DBUnit вставляет в таблицы базы данных в начале выполнения каждого теста.

Листинг 3. Реализация методов getSeedFilesMetaData() и getDBAaccess()
   @Override
   protected SeedFilesMetaData[] getSeedFilesMetaData() {
      String seedFiles[] = { "sampleSeedFile.xml" };
      return new SeedFilesMetaData[] { new SeedFilesMetaData(
            "/sample/process/tests", seedFiles, "SAMPLE") };
   }

   @Override
   protected DBAccess getDBAaccess() {
      return new DBAccess("/sample/process/tests/sampleDBProps.txt");
   }
Листинг 4. Содержание файла свойств sampleDBProps.txt
# Класс драйвера DB2 JDBC
# Не нужно ничего менять, за исключением подключения к
# отличной от DB2 базе данных DbDriver = com.ibm.db2.jcc.DB2Driver

# JDBC URL базы данных
# Убедитесь, что имя хоста и номер порта соответствуют настройкам базы данных
dbUrl=jdbc:db2://localhost:50000/APP_SOR

# Идентификатор пользователя базы данных
dbUser=db2admin

# Пароль пользователя базы данных
dbPassword=dt3t55r6s
Листинг 5. Содержимое файла sampleSeedFile.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
   <table name="ACCOUNT_CATEGORY">
      <column>CATEGORY_ID</column>
      <column>CATEGORY_NAME</column>
      <row>
         <value>1</value>
         <value>Very Important Account</value>
      </row>
      <row>
         <value>2</value>
         <value>Important Account</value>
      </row>
      <row>
         <value>3</value>
         <value>Not So Important Account</value>
      </row>
   </table>

   <table name="REQUEST_TYPE">
      <column>TYPE_ID</column>
      <column>TYPE_NAME</column>
      <row>
         <value>1</value>
         <value>Type 1</value>
      </row>
      <row>
         <value>2</value>
         <value>Type 2</value>
      </row>
      <row>
         <value>3</value>
         <value>Type 3</value>
      </row>
   </table>

   <table name="ACCOUNT">
      <column>ACCOUNT_ID</column>
      <column>ACCOUNT_NAME</column>
      <column>EMAIL</column>
      <column>CATEGORY_ID</column>
      <row>
         <value>1</value>
         <value>ABC</value>
         <value>sales@abc.com</value>
         <value>1</value>
      </row>
      <row>
         <value>2</value>
         <value>XYZ</value>
         <value>sales@xyz.com</value>
         <value>2</value>
      </row>
      <row>
         <value>3</value>
         <value>CBA</value>
         <value>sales@cba.com</value>
         <value>3</value>
      </row>
   </table>

   <table name="REQUEST">
      <column>REQUEST_ID</column>
      <column>ACCOUNT_ID</column>
      <column>DESCRIPTION</column>
      <column>TYPE_ID</column>
      <row>
         <value>1</value>
         <value>1</value>
         <value>A new request for account ABC.</value>
         <value>1</value>
      </row>
      <row>
         <value>2</value>
         <value>2</value>
         <value>A new request for account XYZ.</value>
         <value>2</value>
      </row>
      <row>
         <value>3</value>
         <value>3</value>
         <value>A new request for account CBA.</value>
         <value>3</value>
      </row>
   </table>
</dataset>

Обратите внимание на отношения между записями во всех таблицах, указанных в листинге 5. Например, запись запроса с идентификатором 1 связана с учетными записями ABC и Type 1, а также с категорией Very Important Account.

В листинге 6 приведена реализация метода testVeryImportantRequest() первого теста. Обратите внимание, что этот метод аннотирован JUnit-аннотацией @Test. Метод testVeryImportantRequest() запускает экземпляр процесса Sample BPD, передавая идентификатор запроса. Так как с этим запросом связана категория Very Important Account, выполняемых человеком шагов нет (см. рисунок 4).

Как говорилось ранее, в конце выполнения процесса запись запроса в базе данных обновляется (например, сохраняются поля approved, comments и systemCode). Поэтому реализация метода testVeryImportantRequest() выполняет JUnit-утверждения, чтобы проверить соответствие результатов выполнения процесса ожидаемым результатам. Заметим, что некоторые из этих утверждений выполняются с данными, возвращаемыми вызовом IBM BPM REST API, а другие – с данными, возвращаемыми SQL-запросом (это гарантирует, что бизнес-процесс обновил соответствующую запись запроса должным образом). Кроме того, ожидается получение значения системного кода, поскольку с этой записью запроса связан тип Type 1.

Листинг 6. Реализация метода testVeryImportantRequest()
   @Test
   public void testVeryImportantRequest() throws Exception {
      int requestId = 1;

      // Создайте входной аргумент для запуска бизнес-процесса
      JSONObject bpdArgs = new JSONObject();
      bpdArgs.put("requestId", requestId);

      // Запустите бизнес-процесс Sample BPD
      JSONObject results = bpmClient.runBPD(BPD_ID, PROCESS_APP_ID, bpdArgs);
      int processId = results.getJSONObject("data").getInt("piid");
      Thread.sleep(waitTime);

      // Убедитесь, что процесс завершился как ожидалось
      Assert.assertTrue(utils.isProcessCompleted(processId));

      // Убедитесь, что после выполнения бизнес-процесса
      // в базе данных есть три записи запроса
      int count = getJdbcTemplate().queryForInt(
            "select count(*) from sample.request");
      Assert.assertEquals("Wrong number of request records!", 3, count);

      // Убедитесь, что соответствующая запись запроса была обновлена как ожидалось
     String sql1 = "select approved, system_code, comments from" +
       "sample.request where request_id=" + requestId;
      getJdbcTemplate().query(sql1, new RowCallbackHandler() {
         @Override
         public void processRow(ResultSet rset) throws SQLException {
            String approved = rset.getString(1);
            String systemCode = rset.getString(2);
            String comments = rset.getString(3);
            Assert.assertEquals("System code mismatch!", "ABCD", systemCode);
            Assert.assertEquals("Approval value mismatch!", "Y", approved);
            Assert.assertEquals("Comments mismatch!",
                  "System automated approval", comments);
         }
      });
   }

В листинге 7 приведена реализация метода testImportantRequest() второго теста. Так как с этим запросом связана категория Important Account, выполняется действие Full Review (см. рисунок 4). Поэтому реализация метода testImportantRequest() выполняет JUnit-утверждение для проверки перехода к действию Full Review. Аналогично методу testVeryImportantRequest() метод testImportantRequest() проверяет утверждения с данными, возвращаемыми запросом к IBM BPM посредством REST API, и с данными, возвращаемыми запросом к базе данных. Обратите внимание, что получение значения системного кода не ожидается, поскольку тип Type 1не связан с этой записью запроса. Кроме того, этот метод проверяет, что комментарии и одобренные поля в базе данных имеют ожидаемые значения.

Листинг 7. Реализация метода testImportantRequest()
   @Test
   public void testImportantRequest() throws Exception {
      int requestId = 2;

      // Создайте входной аргумент для запуска бизнес-процесса
      JSONObject bpdArgs = new JSONObject();
      bpdArgs.put("requestId", requestId);

      // Запустите бизнес-процесс Sample BPD
      JSONObject results = bpmClient.runBPD(BPD_ID, PROCESS_APP_ID, bpdArgs);
      int processId = results.getJSONObject("data").getInt("piid");
      Thread.sleep(waitTime);

      // Получите почтовый ящик пользователя
      results = bpmClient.getInbox();

      // Найдите и выполните ожидаемые задания
      JSONObject checkTask = utils
            .findTask(results, processId, "Full Review");
      Assert.assertNotNull(checkTask);
      int checkTaskId = checkTask.getInt("taskId");
      results = bpmClient.startTask(checkTaskId);
      HumanServiceDetails hsDetails = utils.parseStartDetails(results);
      Assert.assertFalse(hsDetails.isCompleted());
      Assert.assertEquals("Full Review", hsDetails.getCoach());

      // Проверьте данные
      JSONObject vars = hsDetails.getVariables();
      Assert.assertNotNull(vars.getJSONObject("request"));
      Assert.assertEquals(requestId,
            vars.getJSONObject("request").getInt("requestId"));
      vars.getJSONObject("request").put("approved", true);
      vars.getJSONObject("request").put("comments",
            "Approving request for XYZ account.");
      bpmClient.setData(checkTaskId, vars);
      results = bpmClient.resumeService(checkTaskId, "buttonGrp1_ok");
      hsDetails = utils.parseResumeDetails(results);
      Assert.assertTrue(hsDetails.isCompleted());
      Thread.sleep(waitTime);

      // Убедитесь, что процесс завершился как ожидалось
      Assert.assertTrue(utils.isProcessCompleted(processId));

      // Убедитесь, что после выполнения бизнес-процесса
      // в базе данных есть три записи запроса
      int count = getJdbcTemplate().queryForInt(
            "select count(*) from sample.request");
      Assert.assertEquals("Wrong number of request records!", 3, count);

      // Убедитесь, что соответствующая запись запроса была обновлена как ожидалось
     String sql1 = "select approved, system_code, comments from" +
       "sample.request where request_id=" + requestId;
      getJdbcTemplate().query(sql1, new RowCallbackHandler() {
         @Override
         public void processRow(ResultSet rset) throws SQLException {
            String approved = rset.getString(1);
            String systemCode = rset.getString(2);
            String comments = rset.getString(3);
            Assert.assertNull("System code mismatch!", systemCode);
            Assert.assertEquals("Approval value mismatch!", "Y", approved);
            Assert.assertEquals("Comments mismatch!",
                  "Approving request for XYZ account.", comments);
         }
      });
   }

В листинге 8 приведена реализация метода testNotSoImportantRequest() (в классе SampleBPDProcessTests) третьего и последнего теста. Так как с этим запросом связана категория Not So Important Account, выполняется действие Quick Review, следующее за действием Get Request (см. рисунок 4). Поэтому реализация метода testNotSoImportantRequest() выполняет JUnit-утверждение для проверки перехода к действию Quick Review, первому действию в этом процессе, выполняемому человеком. Этот метод также выполняет утверждения проверки перехода к действию Full Review, следующему за действием Quick Review (если пользователь Reviewer одобрил запрос). Аналогично двум предыдущим методам теста, testNotSoImportantRequest() выполняет утверждения с данными, возвращаемыми запросом к IBM BPM посредством REST API, и с данными, возвращаемыми запросом к базе данных.

Листинг 8. Реализация метода testNotSoImportantRequest()
   @Test
   public void testNotSoImportantRequest() throws Exception {
      int requestId = 3;

      // Создайте входной аргумент для запуска бизнес-процесса
      JSONObject bpdArgs = new JSONObject();
      bpdArgs.put("requestId", requestId);

      // Запустите бизнес-процесс Sample BPD
      JSONObject results = bpmClient.runBPD(BPD_ID, PROCESS_APP_ID, bpdArgs);
      int processId = results.getJSONObject("data").getInt("piid");
      Thread.sleep(waitTime);

      // Получите почтовый ящик пользователя
      results = bpmClient.getInbox();

      // Найдите и выполните ожидаемое задание -> Quick Review
      JSONObject reviewTask = utils.findTask(results, processId,
            "Quick Review");
      Assert.assertNotNull(reviewTask);
      int reviewTaskId = reviewTask.getInt("taskId");
      results = bpmClient.startTask(reviewTaskId);
      HumanServiceDetails hsDetails = utils.parseStartDetails(results);
      Assert.assertFalse(hsDetails.isCompleted());
      Assert.assertEquals("Quick Review", hsDetails.getCoach());

      // Проверьте данные
      JSONObject vars = hsDetails.getVariables();
      Assert.assertNotNull(vars.getJSONObject("request"));
      Assert.assertEquals(requestId,
            vars.getJSONObject("request").getInt("requestId"));
      vars.getJSONObject("request").put("approved", true);
      vars.getJSONObject("request").put("comments",
            "Approving request for CBA account.");
      bpmClient.setData(reviewTaskId, vars);
      results = bpmClient.resumeService(reviewTaskId, "buttonGrp1_ok");
      hsDetails = utils.parseResumeDetails(results);
      Assert.assertTrue(hsDetails.isCompleted());
      Thread.sleep(waitTime);

      // Получите почтовый ящик пользователя
      results = bpmClient.getInbox();

      // Найдите и выполните ожидаемое задание -> Full Review
      JSONObject checkTask = utils
            .findTask(results, processId, "Full Review");
      Assert.assertNotNull(checkTask);
      int checkTaskId = checkTask.getInt("taskId");
      results = bpmClient.startTask(checkTaskId);
      hsDetails = utils.parseStartDetails(results);
      Assert.assertFalse(hsDetails.isCompleted());
      Assert.assertEquals("Full Review", hsDetails.getCoach());

      // Проверьте данные
      vars = hsDetails.getVariables();
      Assert.assertNotNull(vars.getJSONObject("request"));
      Assert.assertEquals(requestId,
            vars.getJSONObject("request").getInt("requestId"));
      vars.getJSONObject("request").put("approved", false);
      vars.getJSONObject("request").put("comments",
            "Rejecting request for CBA account.");
      bpmClient.setData(checkTaskId, vars);
      results = bpmClient.resumeService(checkTaskId, "buttonGrp1_ok");
      hsDetails = utils.parseResumeDetails(results);
      Assert.assertTrue(hsDetails.isCompleted());
      Thread.sleep(waitTime);

      // Убедитесь, что процесс завершился как ожидалось
      Assert.assertTrue(utils.isProcessCompleted(processId));

      // Убедитесь, что после выполнения бизнес-процесса
      // в базе данных есть три записи запроса
      int count = getJdbcTemplate().queryForInt(
            "select count(*) from sample.request");
      Assert.assertEquals("Wrong number of request records!", 3, count);

      // Убедитесь, что соответствующая запись запроса была обновлена как ожидалось
     String sql1 = "select approved, system_code, comments from" +
       "sample.request where request_id=" + requestId;         
      getJdbcTemplate().query(sql1, new RowCallbackHandler() {
         @Override
         public void processRow(ResultSet rset) throws SQLException {
            String approved = rset.getString(1);
            String systemCode = rset.getString(2);
            String comments = rset.getString(3);
            Assert.assertNull("System code mismatch!", systemCode);
            Assert.assertEquals("Approval value mismatch!", "N", approved);
            Assert.assertEquals("Comments mismatch!",
                  "Rejecting request for CBA account.", comments);
         }
      });
   }

На рисунке 8 показан результат выполнения в Rational® Application Developer трех тестов, определенных в классе SampleBPDProcessTests.

Рисунок 8. Результаты JUnit-тестов
Рисунок 8. Результаты JUnit-тестов

Выполнение тестов на вашей системе

К статье прилагается полный исходный код примеров JUnit- и DBUnit-тестов, выполняющих и проверяющих бизнес-процесс Sample BPD. Также со статьей предоставляется пример бизнес-процесса в виде TWX-файла.

На рисунке 9 показана структура Java-проекта в Rational Application Developer, содержащего JUnit- и DBUnit-тесты для процесса Sample BPD. На рисунке 9 показаны JAR-файлы проекта (все включено в загружаемый .zip-файл). Для выполнения тестов в классе SampleBPDProcessTests эти JAR-файлы нужно включить в classpath виртуальной машины Java (иначе вы получите ошибки ClassNotFoundException). Отметим, что среди этих файлов есть Java REST API-клиент для IBM BPM (bpm-rest-client.jar), который был представлен в предыдущей статье Интеграция приложений бизнес-процессов в IBM Business Process Manager версий V7.5.1 и V8 с внешней системой с помощью REST API (EN).

Рисунок 9. Java проект в Eclipse.
Рисунок 9. Java проект в Eclipse.

Файл download.zip представляет собой архив, содержащий все исходные коды и бинарные файлы, необходимые для запуска примеров, рассмотренных в этой статье. В него также включены DDL-файл, необходимый для создания тестовой базы данных, и TWX-файл, содержащий BPD приложения процесса.

Обратите внимание, что перед запуском тестов, определенных в классе SampleBPDProcessTests, необходимо:

  1. Создать базу данных примера, используя предоставленный файл create-db.sql. Этот DDL-файл был успешно протестирован на базе данных DB2®. Он создает базу данных под именем APP_SOR. Мы не гарантируем, что он будет работать в других базах данных (мы тестировали его только на DB2). Теоретически он должен работать (обратитесь к документации по вашей базе данных).
  2. Создать источник данных (в консоли WebSphere Application Server), ссылающийся на базу данных, созданную на предыдущем шаге. Имя JNDI этого источника данных должно быть jdbc/SampleDS.
  3. Импортировать файл Sample_App_for_JUnit-DBUnit_testing - SAJD_1052012_121_PM.twx. Он содержит бизнес-процесс Sample BPD.
  4. Импортировать в Eclipse файл download.zip в качестве проекта.
  5. Обновить содержимое файлов свойств sampleBPMProps.txt и sampleDBProps.txt.
  6. Выполнить класс SampleBPDProcessTests как JUnit-тест

Упражнение

Мы предлагаем читателю самостоятельно выполнить упражнение по созданию метода четвертого теста (в классе SampleBPDProcessTests):

  1. Запустите экземпляр бизнес-процесса Sample BPD с идентификатором 3.
  2. Убедитесь, что находитесь на шаге Quick Step, первом шаге, выполняемом человеком.
  3. На шаге Quick Review отклоните запрос и оставьте комментарии. Обратите внимание, что в методе testNotSoImportantRequest() пользователь Reviewer одобряет запрос.
  4. Убедитесь, что после выполнения действия Quick Review процесс завершился (например, отсутствует переход к другим действиям, выполняемым человеком).
  5. Убедитесь, что поле systemCode в базе данных не имеет значения (например, его значение NULL).
  6. Убедитесь, что поля comments и approved в базе данных содержат ожидаемые значения.

Заключение

В статье продемонстрировано написание автоматизированных тестов для IBM BPM бизнес-процессов с использованием JUnit, DBUnit и Java REST API client. Автоматизированные тесты для процессов IBM BPM позволяют гарантировать, что процессы работают ожидаемым образом. Можно создать тесты для всех путей выполнения, существующих в процессе, и получить набор тестов для регрессионного тестирования при внесении изменений в реализацию процесса. Автоматизированные тесты позволяют утверждать, что человек выполнил ожидаемые шаги, проверить данные "на лету", убедиться, что процесс завершился успешно (без ошибок), и проверить состояние данных в базе данных.


Загрузка

ОписаниеИмяРазмер
Пример кодаdownload.zip7068 КБ

Ресурсы

Научиться

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java
ArticleID=948083
ArticleTitle=Автоматизация контрольных тестов приложений бизнес-процессов на Java при помощи IBM Business Process Manager
publish-date=10112013