Введение. Повышение роли тестирования с переходом на архитектуру клиент-сервер
В нашей стране в силу ряда причин большие ЭВМ (так называемые мэйнфреймы) не могли оказать реального воздействия на информационные технологические процессы организаций, учреждений, предприятий*). Персональные компьютеры, как правило, автоматизируют конкретные рабочие места. Только с развитием технологии клиент-сервер появилась возможность реально воздействовать на организацию бизнеса посредством внедрения соответствующего программного обеспечения (ПО). Такое ПО, естественно, становится все более сложным, и его использование вменяется в обязанности конечного пользователя. С точки зрения тестирования такого ПО, появляется ряд новых моментов.
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.
Слева: стандартный доступ к данным при работе приложения; справа: доступ к данным серверной части приложения с помощью SQLBench.
Как работает SQLBench?
· Рабочие процессы и поведение конечных пользователей (вызов транзакций, ввод данных, режимы работы пользователей) воспроизводятся имитатором.
· Вместо транзакций используются их прототипы. Прототип транзакции в SQLBench осуществляет доступ к данным и управление выполнением данной транзакции. Не требуется задавать пользовательский интерфейс транзакции, поскольку он не влияет на показатели работы системы клиент-сервер. Затраты на разработку прототипа транзакции значительно меньше, чем на разработку реальной транзакции.
· Если на момент запуска SQLBench вы не располагаете данными относительно работы системы в реальных условиях, то требования, относящиеся к системе данных, должны имитироваться как часть рабочей нагрузки, которая генерируется с использованием тестовых данных. Для реализации этого SQLBench предлагает большое количество функций генерации случайных тестовых данных.
· Результаты имитации выдаются на экран, а также сохраняются в файлах результатов и в базе данных результатов. SQLBench сообщает результаты по времени отклика, пропускной способности, по возникающим коллизиям доступа к данным. Может быть сформировано несколько различных вариантов отчета о результатах: на уровне транзакций, команд SQL, операторов FETCH.
Имитатор обеспечивает следующие возможности:
· несколько случайных функций (экспоненциальный, равномерный, биномиальный законы распределения), которые используются для имитации поведения конечного пользователя;
· случайный вызов транзакций пользователя, случайная генерация входных значений;
· управление логикой запуска транзакций, имитация случайной интерактивной работы пользователя с данными.
"Живой" пользователь не нужен. Работа многих пользователей имитируется на одном компьютере, который должен иметь доступ к данным на сервере.
В прототипе транзакции определяются логика приложения и операторы доступа к данным в пределах транзакций, интерфейс с пользователем не описывается, доступ к данным программируется на SQL. Это обеспечивает достаточно низкую стоимость разработки транзакций (около 5% стоимости программирования на 4GL).
Что измеряется:
· среднее время отклика;
· максимальное время отклика;
· минимальное время отклика;
· дисперсия времени отклика;
· процент измерений, когда время отклика меньше некоторого предела.
На рис. 2 показан пример результатов измерений, полученных с помощью SQLBench.
|
|||||||||||
|
|
|
avg |
max |
min |
|
< 1 sec |
< 2 sec |
|||
|
|
|
|
|
|
|
|
|
|||
FETCH ALL FETCH SET UNIQUE WAIT UPD_PRICE TIMER_PRICECHANGE |
25 105 105 105 25 |
0.51 0.19 6.71 0.41 29.13 |
1.31 1.47 22.90 6.97 66.59 |
0.12 0.00 0.19 0.00 12.25 |
0.33 0.37 5.45 1.31 15.59 |
90% 92% 1% 91% 0% |
100% 100% 21% 95% 0% |
Рисунок 2.
Пример результатов измерений, полученных с помощью SQLBench.
В процессе тестирования могут быть выявлены клинчи при доступе к данным. На рис. 3 приведен пример таких результатов. Код ошибки 1801 - это код для СУБД SQLBase. Указывается имя транзакции и команды SQL, номер обращения и имя курсора.
|
|||||||
|
|
|
|
|
|
|
|
10:09:24 10:12:15 ..... 10:55:18 |
SELLING SELLING ..... SELLING |
5 47 ..... 726 |
INSERT_CASHBOOK INSERT_CASHBOOK ..... INSERT_CASHBOOK |
SQLEXE SQLEXE ..... SQLEXE |
C2 C2 ..... C2 |
1 1 ..... 1 |
1801 1801 ..... 1801 |
Рисунок 3.
Пример выявления клинчей при доступе к данным.
SQLBench поддерживает SQLBase и все серверы баз данных, доступные через драйверы ODBC и SQLNetwork, - Oracle, Informix, Sybase, MS SQL Server, AS/400 и другие.
На рис. 4 показана общая последовательность действий при применении SQLBench: тест сначала должен быть написан на специальном языке, после чего он компилируется. Естественно, выдаются сообщения с диагностикой ошибок и точной привязкой к месту ошибки в программе теста. Возможно подключение к серверу для контроля синтаксиса SQL-команд. При отсутствии ошибок в тексте тест может быть запущен на выполнение.
Общая последовательность действий при применении 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.
*) Напоминаем, что мнения авторов не обязательно совпадают с мнением редакции журнала.