Введение. Повышение роли тестирования с переходом на архитектуру клиент-сервер
Общая характеристика SQLBench. Концепция построения и использования
Как работает SQLBench?
Структура программы теста в SQLBench
Пример теста
Кому и когда может быть полезен SQLBench?
Основные характеристики SQLBench

Введение. Повышение роли тестирования с переходом на архитектуру клиент-сервер

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

1) Клиент-серверные системы часто действуют в гетерогенной среде (где применяется продукция разных поставщиков). Отсюда проблема стыковки. Ситуация осложняется еще и тем, что всегда существует разрыв между тем, что поставщики обещают, и реальным поведением продуктов.

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

3) Необходимо тестировать серверную часть приложения с целью оценки производительности и поведения на различных уровнях нагрузки в условиях многопользовательского доступа к данным.

Таким образом, при разработке приложений в архитектуре клиент-сервер необходимо тестировать:

1) GUI из различных комбинаций меню, пиктограмм, окон и других объектов;

2) интерфейс между клиентской и серверной частями, включая транзакции;

3) функционирование сервера, эффективность и надежность параллельной обработки транзакций;

4) функционирование сети, надежность и производительность при пиковых нагрузках.

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

Автор не ставит в качестве своей задачи полное освещение вопросов автоматизации тестирования, а хочет обратить внимание заинтересованных на довольно простое и легкое в использовании средство под названием SQLBench, которое решает достаточно оригинальным способом лишь вопрос тестирования серверной части клиент-серверных приложений. Производителем этого средства является австрийская фирма ARC (Ambichl&Reindl Communication OEG). Такой выбор объясняется большой полезностью этого средства для широкого круга специалистов, не только разрабатывающих ПО на заказ, но и стоящих перед проблемами выбора соответствующего SQL-сервера и внедрения ПО в архитектуре клиент-сервер в своих организациях.

Общая характеристика SQLBench. Концепция построения и использования

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

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

После того как с помощью, например, ERwin построена логическая и физическая модели данных, произведена генерация схемы базы данных в среде СУБД, выбранной в качестве сервера, т.е. созданы незаполненные данными таблицы и индексы, можно начинать работать с SQLBench. Пользователю предоставляются две главные возможности - сгенерировать и заполнить базу данных случайными тестовыми данными любого объема, а затем описать на специальном языке прототип будущего приложения и произвести имитацию доступа к данным на сервере со стороны многих пользователей приложения.

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

Picture 1

Рисунок 1.
Слева: стандартный доступ к данным при работе приложения; справа: доступ к данным серверной части приложения с помощью SQLBench.

Как работает SQLBench?

· Рабочие процессы и поведение конечных пользователей (вызов транзакций, ввод данных, режимы работы пользователей) воспроизводятся имитатором.

· Вместо транзакций используются их прототипы. Прототип транзакции в SQLBench осуществляет доступ к данным и управление выполнением данной транзакции. Не требуется задавать пользовательский интерфейс транзакции, поскольку он не влияет на показатели работы системы клиент-сервер. Затраты на разработку прототипа транзакции значительно меньше, чем на разработку реальной транзакции.

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

· Результаты имитации выдаются на экран, а также сохраняются в файлах результатов и в базе данных результатов. SQLBench сообщает результаты по времени отклика, пропускной способности, по возникающим коллизиям доступа к данным. Может быть сформировано несколько различных вариантов отчета о результатах: на уровне транзакций, команд SQL, операторов FETCH.

Имитатор обеспечивает следующие возможности:

· несколько случайных функций (экспоненциальный, равномерный, биномиальный законы распределения), которые используются для имитации поведения конечного пользователя;

· случайный вызов транзакций пользователя, случайная генерация входных значений;

· управление логикой запуска транзакций, имитация случайной интерактивной работы пользователя с данными.

"Живой" пользователь не нужен. Работа многих пользователей имитируется на одном компьютере, который должен иметь доступ к данным на сервере.

В прототипе транзакции определяются логика приложения и операторы доступа к данным в пределах транзакций, интерфейс с пользователем не описывается, доступ к данным программируется на SQL. Это обеспечивает достаточно низкую стоимость разработки транзакций (около 5% стоимости программирования на 4GL).

Что измеряется:

· среднее время отклика;

· максимальное время отклика;

· минимальное время отклика;

· дисперсия времени отклика;

· процент измерений, когда время отклика меньше некоторого предела.

На рис. 2 показан пример результатов измерений, полученных с помощью SQLBench.

Project: SIMS
Benchmark: Price
Date/time: 96-06-27/13:30:00
Simulation Duration: 1800 sec
User
CH
Measuring Entity
Status
Count
RT
avg
RT
max
RT
min
Dev
RT
< 1 sec
RT
< 2 sec
PRICECHANGE
OK
25
31.97
67.22
12.81
14.48
0%
0%
SEL_ARTICLECATEGORY
FETCH ALL
FETCH SET UNIQUE
WAIT
UPD_PRICE
TIMER_PRICECHANGE
25
25
105
105
105
25
1.11
0.51
0.19
6.71
0.41
29.13
7.31
1.31
1.47
22.90
6.97
66.59
0.07
0.12
0.00
0.19
0.00
12.25
2.02
0.33
0.37
5.45
1.31
15.59
63%
90%
92%
1%
91%
0%
90%
100%
100%
21%
95%
0%

Рисунок 2.
Пример результатов измерений, полученных с помощью SQLBench.

В процессе тестирования могут быть выявлены клинчи при доступе к данным. На рис. 3 приведен пример таких результатов. Код ошибки 1801 - это код для СУБД SQLBase. Указывается имя транзакции и команды SQL, номер обращения и имя курсора.

Errors
Time
Transaction
SQL Command
API
Cur
-Class
E-Code
10:09:22
10:09:24
10:12:15
.....
10:55:18
SELLING
SELLING
SELLING
.....
SELLING
4
5
47
.....
726
INSERT_CASHBOOK
INSERT_CASHBOOK
INSERT_CASHBOOK
.....
INSERT_CASHBOOK
SQLEXE
SQLEXE
SQLEXE
.....
SQLEXE
C2
C2
C2
.....
C2
1
1
1
.....
1
1801
1801
1801
.....
1801

Рисунок 3.
Пример выявления клинчей при доступе к данным.

SQLBench поддерживает SQLBase и все серверы баз данных, доступные через драйверы ODBC и SQLNetwork, - Oracle, Informix, Sybase, MS SQL Server, AS/400 и другие.

На рис. 4 показана общая последовательность действий при применении SQLBench: тест сначала должен быть написан на специальном языке, после чего он компилируется. Естественно, выдаются сообщения с диагностикой ошибок и точной привязкой к месту ошибки в программе теста. Возможно подключение к серверу для контроля синтаксиса SQL-команд. При отсутствии ошибок в тексте тест может быть запущен на выполнение.

Picture 4

Рисунок 4.
Общая последовательность действий при применении SQLBench.

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

Структура программы теста в SQLBench

Программа теста состоит из следующих компонентов:

· компонент случайных переменных;

· компонент рабочей нагрузки;

· компонент транзакций;

· SQL-компонент.

Компонент случайных переменных нужен для описания случайных переменных, которые далее будут использоваться для:

· генерации случайных входных значений;

· определения случайных коэффициентов повторения;

· определения вероятности запуска компонентов транзакций;

· определения случайных временных характеристик пользователя.

Пример:
  DCLRAND
  randvar1: RndUniN(1..1000);
  randvar2: RndStr("abcde1234"; 10..20);
  ...

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

DCLUSER
  USER usr1: 3600,300,200;
  TRANSACTIONS
    Selling:100;
    Order:10;
  USER usr2,usr3: 2000,300,200;
    StockQuery:20;
  ...

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

DCLTRANS
  TRANSACTION Selling:
  VAR i,artno: NUMBER;
      name,agr: STRING(40);
  BEGIN
    FOR i:=1 TO 5 DO
      artno:=randvar1;
      c1: SelArticle(IN artno; OUT name,agr);
      c2: InsSale(...);
    END;
  END Selling;

  TRANSACTION Order:
  TRANSACTION StockQuery:
...

SQL-компонент содержит определение команд SQL, вызываемых в прототипах транзакций, и именно тех, которые могут быть использованы в окончательной системе. Пример:

DCLSQL
  SelArticle(IN ano:NUMBER;
             OUT name,agr:STRING(40); pr:NUMBER):
    select article_name,price,article_group
    into :name, :pr , :agr
    from artikel where artno = :ano;

  InsSale(...):
    ...

Пример теста

/****************************************
* TP1 Benchmark Test
****************************************/
/****************************************
* Table    Rows
* ======== =====
* account  10000 * x
* teller   10 * x
* branch   1 * x
* history 0
****************************************/
BENCHMARK TP1BM
DATABASE tp1db

CONST
/*-----------------------*
* change these constants 
 for changing workload
*-----------------------*/
  MAXACCOUNT_REC      := 20000;
/* MAXACCOUNT_REC / MAX_LOOP: */
  MAXACCOUNT_TRA      := 200;
  MAXTELLER           := 20;
  MAXBRANCH           := 2;
  MAXTP1              := 450;
/*-----------------------*/
  MAX_LOOP            := 100;
  ACCOUNTS_PER_TELLER := 1000;
  ACCOUNTS_PER_BRANCH := 10000;

VAR
/*-----------------------*
* variables for binding data
*-----------------------*/
  vAcc,vTel,vBra,vDelta: number;

DCLRAND
/*-----------------------*
* randoms for loading test data
*-----------------------*/
  lfdAcc :RndSno(0);
  lfdTel :RndSno(0);
  lfdBra :RndSno(0);

/*-----------------------*
* randoms for simulating the workload
*-----------------------*/
  rAcc :RndUniN(1..MAXACCOUNT_REC);
  rEvent :RndBin(0.15);

DCLUSER
/*-----------------------*
* user for loading test data
*-----------------------*/
  user
    sysadm: 0,0,0;
  transactions
    LoadAcc: MAXACCOUNT_TRA;
    LoadTel: MAXTELLER;
    LoadBra: MAXBRANCH;

/*-----------------------*
* users for simulating the workload
*-----------------------*/
  user
    u1,u2,u3,u4,u5,u6,u7,u8,u9,u10: 0,0,0;
  transactions
    TP1: MAXTP1;

DCLTRANS
/*-----------------------*
* transactions for loading test data
*-----------------------*/
  transaction LoadAcc
  var i: number;
  begin
    for i:=1 to MAX_LOOP do
      c1: InsAccount(rr);
    end;
  end LoadAcc;

  transaction LoadTel
  begin
    c1: InsTeller(rr);
  end LoadTel;

  transaction LoadBra
  begin
    c1: InsBranch(rr);
  end LoadBra;

/*-----------------------*
* transaction for simulating the workload
*-----------------------*/
  transaction TP1
  begin
    vAcc:=rAcc-1;
    vTel:=vAcc/ACCOUNTS_PER_TELLER;
    vBra:=vAcc/ACCOUNTS_PER_BRANCH;

    /*---------------------*
    * make transaction inter-branch
    * in 15% of the cases (rEvent)
    * (if MAXBRANCH > 1 branch)
    *---------------------*/

    if (MAXBRANCH>1) and rEvent then
      loop
        vAcc:=rAcc-1;
        if vAcc/ACCOUNTS_PER_BRANCH <> 
        vBra then exit end;
      end;
    end;

    vDelta := RndUniN(1..2);

    c1: UpdAccount(rr);
    c2: UpdTeller (rr);
    c3: UpdBranch (rr);
    c4: InsHistory(rr);
  end TP1;

DCLSQL
/*-----------------------*
* SQL commands for loading test data
*-----------------------*/
  InsAccount(stored):
    insert into account
    values(:lfdAcc,"NAME field length 20",
      "BRANCH 8","ALTNUM 8","JOINK 8",
      "FIELD 7","FIELD 8","FIELD 9",
      "F10 6","F114",1000);

  InsTeller(stored):
    insert into teller
    values(:lfdTel,"NAME field length 20",
      "BRANCH 8","ALTNUM 8","JOINK 8",
      "FIELD 7","FIELD 8","FIELD 9",
      "F10 6","F114",1000);

  InsBranch(stored):
    insert into branch
    values(:lfdBra,"NAME field length 20",
           "BRANCH 8","ALTNUM 8","JOINK 8",
           "FIELD 7","FIELD 8","FIELD 9",
           "F10 6","F114",1000);

/*-----------------------*
* SQL commands for simulating the workload
*-----------------------*/
  UpdAccount(stored):
    update sysadm.account
    set bal = bal + :vDelta
    where num = :vAcc
    and ((bal + :vDelta) > 0)
    check exists;

  UpdTeller(stored):
    update sysadm.teller
    set bal = bal + :vDelta
    where num = :vTel
    check exists;

  UpdBranch(stored):
    update sysadm.branch
    set bal = bal + :vDelta
    where num = :vBra
    check exists;

  InsHistory(stored):
    insert into sysadm.history
    values (:vAcc,:vTel,:vBra,:vDelta,
      SYSDATETIME);

END TP1BM

Ниже приводится описание скрипта, содержащего определения таблиц и прав пользователей для обеспечения работы вышеприведенного теста.

grant connect to 
   u1,u2,u3,u4,u5,u6,u7,u8,u9,u10
identified by 
   u1,u2,u3,u4,u5,u6,u7,u8,u9,u10;
grant dba to 
   u1,u2,u3,u4,u5,u6,u7,u8,u9,u10;

create table account
  (num decimal(10,0),
  name char(20),
  branch char(8),
  altnumber char(8),
  joinkey char(8),
  field7 char(8),
  field8 char(8),
  field9 char(8),
  field10 char(6),
  field11 char(4),
  bal decimal(12,2));

create table teller
  (num decimal(10,0),
  name char(20),
  branch char(8),
  altnumber char(8),
  joinkey char(8),
  field7 char(8),
  field8 char(8),
  field9 char(8),
  field10 char(6),
  field11 char(4),
  bal decimal(12,2));

create table branch
  (num decimal(10,0),
  name char(20),
  branch char(8),
  altnumber char(8),
  joinkey char(8),
  field7 char(8),
  field8 char(8),
  field9 char(8),
  field10 char(6),
  field11 char(4),
  bal decimal(12,2));

create table history
  (account decimal(10,0),
  teller decimal(10,0),
  branch decimal(10,0),
  delta decimal(10,2),
  timex datetime);

create index xaccount on account(num) 
  pctfree 0;

create index xteller on teller(num) 
  pctfree 0;

create index xbranch on branch(num) 
  pctfree 0;
commit;

Кому и когда может быть полезен SQLBench?

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

Может быть зафиксировано влияние любых изменений в прикладном ПО:

· добавление новых транзакций;

· добавление новых объектов (данных);

· изменение количественных характеристик;

· добавление новых пользователей.

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

С помощью SQLBench можно подготовить стандартные тесты оценки производительности и таким образом производить также выбор СУБД, наиболее подходящей для нужд организации.

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

Итак, SQLBench может быть полезна широкому кругу специалистов, среди которых:

· проектировщики БД;

· администраторы БД;

· управляющие проектами;

· группа оценки качества;

· поставщики ПО;

· переходящие к системам клиент-сервер пользователи;

· менеджеры по продаже;

· поставщики БД.

Основные характеристики SQLBench

Инструмент тестирования SQLBench:

· не зависит от средств разработки клиентской части;

· поддерживает стандартные тесты производительности для предварительного анализа;

· позволяет оценивать производительность на основе индивидуальной нагрузки;

· использует единственную рабочую станцию для имитации нагрузки от многих пользователей;

· может быстро генерировать тестовые данные;

· способен производить выборочное тестирование (только критических компонентов);

· прост в изучении;

· не требует участия реального пользователя для оценки производительности.

Отметим также:

· низкие затраты на разработку тестов (около 5% затрат при использовании 4GL);

· высокий процент повторного применения сценариев (около 50%);

· возможность использования сценариев SQLBench в качестве спецификации.


Олег Владимирович Чикало,
"ИНТЕРФЕЙС, Лтд.",
тел.: 135-55-00, 135-25-19.


*) Напоминаем, что мнения авторов не обязательно совпадают с мнением редакции журнала.