четверг, 16 апреля 2009 г.

Разоблачение Excel:
Проверка вводимых данных - выпадающие списки



Часто ли у вас возникало желание, после получения отчета в Excel (абсолютно на любую тематику), убить его автора? Если возникало и не раз – скорее всего вы наш пациент :)






1. Отчёт, отчёт и еще раз …?

Казалось бы чем можно убить любую здравую идею, подразумевающую некоторую информационную составляющую: ”Давайте соберем статистику использования различных операционок на проектах”, “Надо бы собрать сведения об используемом ПО для оптимизации расходов компании” и т.д.?

Правильно – бездарно собранной информацией!!!

Итак, смотрим, что мы получили в ответ на наш запрос:

Раз



И два



С одной стороны вроде и информация собрана, а с другой…

Бухгалтррия Плюс – это почти Бухгалтерия Плюс, но не совсем.
Антиврус (ПО) – это почти Антивирус (ПО), но не совсем.
Отдел сопровждения ПО – это почти Отдел сопровождения ПО, но не совсем.

И уж совсем ни одно и тоже Windows XP, Win XP, XP, WinXP.
Как впрочем и 1C Бухгалтерия, 1C, 1C Бухгалтерия 7.0.

Поэтому, засучив рукава, идем за большим напильником и начинаем … :)

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


2. Очень гибко хорошо, очень гибко плохо?

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

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

Все казалось бы верно, но возвращаясь к собранным отчетам, возникает чувство некоторой неполноценности: ”А можно, чтобы все также просто как в Excel, но еще и чтобы контроль данных был?” (перед глазами заботливо всплыл образ Никулина и его ”перламутровые пуговицы”).
И чтобы тоска от сознания необходимости ковырятся в VB for application, макросах, формулах не потушила робкую надежду, как минимум, дочитать эту статью до конца, а как максимум, реализовать то, что в ней написано, сразу ответим – можно и это не так уж сложно, как может показаться на первый взгляд.

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


3. Готовим прокрустово ложе.

Для начала нам нужно подготовить корректные значения для заполнения наших выпадающих списков правильными величинами. Это можно сделать на отдельной странице нашего Excel файла, назовем её просто и незатейливо – ”Списки (первый вариант)” и скопируем в нее наш список проектов.



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



И активируем диалог валидации данных ( Main menu>Data>Data Validation ) для выбранной ячейки



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

Первая страница диалога – Settings (в большинстве случаев её оказывается достаточно) позволяет вам ограничить входные данные согласно заданным правилам. Для настройки необходимого нам типа валидации следует выбрать значение выполнить установки согласно картинке ниже, то есть Allow = List.

Обратите внимание,что на странице появились дополнительные элементы управления:
In-cell dropdown – говорит, что значения предлагаются в виде выпадающего списка;
Source – указывает где брать допустимые значения.



Вторая страница – Input Message пытается ”отпугнуть” неправильные значения еще на ближних подступах, а точнее при активации ячейки. После перехода в ячейку с активированным данным типом валидации появляется всплывающая подсказка с вашим текстом. Но я бы советовал пользоваться данным типом предупреждений очень осторожно потому, что при активной работе такие подсказки больше раздразжают, чем помогают.



Более удобный вариант подсказки предполагает использование вкладки Error Alert. При использовании этого варианта сообщения появляются при попытке выхода из поля при условии неправильного введенного значения.



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



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

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


3.1. Огласите весь список, пожалуйста.

Оказывается “огласить” список допустимых значений тоже можно не одним способом, а как минимум тремя.

Перечисление списка допустимых значений.
Первый и самый простой (именно этот способ и запечатлен на рисунке выше) – это перечисление списка значений через разделитель ; напрямую в поле Source первой вкладки:



Быстро, понятно, удобно и …
не стоит так делать (точнее делать можно, но предварительно хорошо подумав)

Представим ситуацию, когда таким образом провалидированные поля разбросаны щедрой рукой по всему Excel файлу и вдруг оказывается, что нужно добавить в список допустимых значений еще одну строчку!
Поэтому, хорошенько подумав такой стиль оформления применяйте только для абсолютно фиксированных небольших списков, например: {Да;Нет}, {M;Ж}, {Pass;Fail}

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



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

Именованный диапазон.
Оформив наш список значений в виде именованного диапазона с логичным и понятым для вас именем (в данном случае ”Проекты”). Мы можем вместо буквенно-числовой шифрограммы $A$2:$A$8 использовать осмысленное имя – Проекты.





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


4. Выводы

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


P.S. Для лентяев (к которым я причисляю и себя) в комментариях можно найти ссылу на Excel-файл, являющийся материализацией вышеизложенного материала.

С уважением,
Сергей Талалаев


Read more...

понедельник, 13 апреля 2009 г.

Нас публикуют за рубежом!



В рамках реализации проекта по перемещению мировой столицы тестирования в Минск (О.Бендер и Нью-Васюки нервно курят) состоялась публикация нашей статьи на специализированном сайте по автотестированию AdvancedQTP.com

А если серьезно, то ...


Я очень благодарен этому профессиональному сайту. Начиная с первой страницы (один слоган чего стоит: 'coz we're programmers - not users) становится понятно, что аудитория здесь собралась крайне серьезная. Мне очень повезло, что начиная свой путь с QTP я столкнулся именно с этим ресурсом. Многие сложные оказались предельно простыми после ознакомления с материалами, размещенными на сайте.
Кроме того, в силу ограничений коммерческого характера (и мне это абсолютно понятно), некоторые статьи не раскрывают все технические тонкости реализации какой-либо интересной функциональности, но дают представление об идее, которую приходится доводить до ума самостоятельно (что потрясающе интересно).

Думаю, что заслуженных диферамбов получилось достаточно :)

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

Честно говоря, были некоторые сомнения насколько окажется интересным материал, попадает ли он в тематику сайта, уровень владения языком опять-же. Но, спасибо активисту и основному редактору ресурса - Yaron Assa за его позитивный настрой и активность, статья была принята с хорошей оценкой с его стороны.

Поэтому, приглашаю вас во-первых, посетить этот действительно профессиональный ресурс, а во-вторых, порадоваться вместе с нами: AdvancedQTP-Universal class for data manipulations

С уважением,
Сергей Талалаев

С большой признательностью к моей коллеге Анне Валерьевне.

Read more...

понедельник, 6 апреля 2009 г.

Учим тестированию студентов!

В одном из своих постов я уже говорила о том, что среди прочих грандиозных планов - преподавание курса по тестированию ПО студентам БГУИР.

Свершилось!

И вот уже с 11-го марта дважды в неделю я наслаждаюсь общением со студентами на тему тестирования!
Признаться, до начала курса настороженно относилась к тому, как пойдет общение. Но, как ни странно, студенты ведут себя очень заинтересованно и активно. И что особенно приятно - они задают вопросы! А это значит, что:
- Они не боятся
- Они слушают
- Они пытаются разобраться
- Им небезразлично
- И, надеюсь, они, в итоге, усваивают
По поводу последнего утверждения могу сказать следующее: кое-что усваивают точно, потому что часто слышу: "а вот Вы говорили так-то", "а это называется так-то", "а такие-то тесты писать будем?" и т.д. и т.п.
Ну, а все остальное мы проверим на итоговой работе...

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

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

Пока, как говорится, "Учиться! Учиться! и еще раз - Учиться!"
Ждем результатов :)

Всегда ваша,
Наташа Густыр


Read more...

четверг, 2 апреля 2009 г.

QTP: Сравнивая с …
Универсальный класс для работы с данными


Влияние мирового кризиса к сожалению сказалось и на моей персоне и мне потребовалось срочно и по возможности глубоко изучить новый для себя фреймворк - Quick Test Professional. И душа рвется поведать о результатах, которые надеюсь буду полезны не только мне одному.

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


1. Введение

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


2. Работа с Excel-данными

Еще работая с WinRunner, я убедился, что встроенная реализация Excel хранилища не настолько гибка, как мне бы хотелось. Поэтому, как всегда, я приготовился к миграции своих процедур для работы с Excel. И был немного удивлен отсутствию встроенных средств работы с БД. Но эта задача вполне по силам, когда за плечами вся мощь VB :)


2.1. Основные задачи

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

Эти трудносовместимые вещи отлично реализуются посредством встроенной в Excel валидации входных данных и также прекрасно уничтожаются попыткой редактирования Excel таблицы напрямую из QTP.
Более того уничтожается также любое кастомное форматирование, без которого нормально читаемая таблица превращается в клетчатый текст.

Было до вмешательства из QTP:



Стало после редактирования из QTP:



Чтобы избежать подобных казусов я давно применяю прямую вычитку из Excel файлов в массивы, используя для этого стандартные ODBC источники. Данная техника успешно прижилась уже на следующих тестовых фреймворках: Rational Robot, IBM Rational Functional Tester, WinRunner и надеюсь QTP

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


2.2. Предварительные шаги

В Excel документах имеется функциональность которая позволяет выделять значимые для пользователя подмножества ячееек в специальные структуры. Такие структуры называемые “именованными диапазонами” обеспечивают возможность обращаться к ним к ним через логические имена.
Кроме того (что гораздо более значимо для нас) такие диапазоны становятся видны как стандартные ODBC таблицы из внешних приложений.

Итак, для оформления требуемой совокупности ячеек в качестве “именованного диапазона” необходимо выполнить следющую последовательность действий:
- выделить все ячейки, планируемые для оформления в именованный диапазон
- создать именованный диапазон через “Define name” диалог (Formulas > Define Name)



или напрямую введя имя диапазона в Navigation Bar.



Для проверки корректности вновь созданного именованного диапазона – выделите все ячейки диапазона и проверьте значение в Navigation Bar. Он должен содержать логическое имя вместо A1 нотации.

Важно отметить одно требование обязательно при использовании именованных диапазонов в качестве источника данных:
- первая строка нашего диапазона должна содержать имена столбцов, а не данные


2.3. Со стороны функциональной библиотеки

После всех подготовительных шагов осталось совсем немного поработать руками, а точнее пописать код.
Раз уж QTP 9.5 предоставил нам замечательную возможность работать c “почти” объектами – грех было бы ей не воспользоваться. Поэтому весь наш функционал мы гордо завернем в класс с благозвучным названием TestData.

Стоит напомнить, что QTP не видит напрямую классы, объявленные во внешних библиотеках, поэтому для каждого класса должна присутствовать функция создания экземпляра класса, в данном случае – CreateTestData

Кроме того мы должны иметь возможность инициировать наш класс не только через загрузку из Excel источника но и напрямую из кода. Именно для этих целей появились два метода: SetData и GetData


Public Function CreateTestData ()
Set CreateTestData = new TestData
End Function

Class TestData
Private mTestTable()

Private Sub Class_Initialize()
End Sub

Private Sub Class_Terminate()
Erase mTestTable
End Sub


' @Documentation Initiates TestData object with external data
'-----------------------------------------------------------

Public Sub SetData (DataArr())
Dim i,j

ReDim mTestTable(UBound(DataArr, 1), UBound(DataArr, 2))
For i=0 to UBound(DataArr, 1)
For j=0 to UBound(DataArr, 2)
mTestTable(i,j) = DataArr(i,j)
Next
Next
End Sub


' @Documentation Extracts data from TestData object
'---------------------------------------------------

Public Sub GetData(DataArr())
Dim i,j

ReDim DataArr(UBound(mTestTable, 1), UBound(mTestTable, 2))
For i=0 to UBound(mTestTable, 1)
For j=0 to UBound(mTestTable, 2)
DataArr(i,j) = mTestTable(i,j)
Next
Next
End Sub


Итак, мы вплотную подобрались к центральной части нашего функционала – вычитке данных из Excel источника.
За данную часть функционала отвечают два взаимосвязанных метода: GetArrayFromStore и LoadFromStore
Первый позволяет нам выгрузить вычитанные данные во внешний массив, минуя наш класс, а второй наоборот – инициирует наш класс вычитанными данными.


' @Documentation Extracts test data from the Excel store
'------------------------------------------------------

Public Sub GetArrayFromStore(Arr(), TableName, StoreName)
Dim Connection
Dim i, j, fieldcount, rowsfetched
Dim ArrTemp()

Set Connection = CreateObject("ADODB.Connection")
Connection.ConnectionString = "DBQ=" + StoreName + _
";Driver={Microsoft Excel Driver (*.xls)}" + _
";DriverId=790;FIL=excel 8.0;MaxBufferSize=2048" + _
";MaxScanRows=8;PageTimeout=5;ReadOnly=1" + _
";SafeTransactions=0;Threads=3;UserCommitSync=Yes"
Connection.Open

Set ConnRs = CreateObject("ADODB.Recordset")
ConnRs.CursorType = 3
Call ConnRs.Open("select * from " + TableName, Connection)

fieldcount = ConnRs.Fields.Count
Redim ArrTemp(fieldcount - 1, 0)

'column names adding
for j=0 to fieldcount - 1
ArrTemp(j,0) = ConnRs.Fields(j).Name
next

rowsfetched = 0
ConnRs.MoveFirst()
While not ConnRs.Eof
rowsfetched = rowsfetched + 1
Redim Preserve ArrTemp(fieldcount - 1, rowsfetched)
for j=0 to fieldcount - 1
ArrTemp(j, rowsfetched + i) = ConnRs(j).value
next
ConnRs.MoveNext()
Wend
Connection.Close

'matrix transposition
Redim Arr(UBound(ArrTemp,2), UBound(ArrTemp,1))
for i=LBound(ArrTemp,1) to UBound(ArrTemp,1)
for j=LBound(ArrTemp,2) to UBound(ArrTemp,2)
Arr(j,i) = ArrTemp(i,j)
next
next

End Sub


' @Documentation Loads test data from Excel store to the TestData object
'-----------------------------------------------------------------------

Public Sub LoadFromStore (TableName, StoreName)
call GetArrayFromStore(mTestTable, TableName, StoreName)
End Sub


Как вы можете заметить, ничего сверхъестественного в реализации данного функционала нет. Более того очевидно, что с небольшими модификациями такую же процедуру можно применять для вычитки данных из любого ODBC источника.
Нам осталось добавить несколько сервисных методов, чтобы наш класс стал действительно удобным в использовании: GetCellByIndex, GetCellByName, ColumnCount, RowCount


' @Documentation Gets cell value by row-column indexes
'------------------------------------------------------

Public Function GetCellByIndex (RowIndex, ColumnIndex)
GetCellByIndex = mTestTable(RowIndex+1, ColumnIndex)
End Function


' @Documentation Gets cell value by column name and row index
'-------------------------------------------------------------

Public Function GetCellByName (ColumnName, RowIndex)
Dim j

for j = 0 to UBound(mTestTable,2)
If (ColumnName = mTestTable(0,j)) Then
Exit For
End if
next

GetCellByName = mTestTable(RowIndex+1, j)
End Function


' @Documentation Returns number of columns into the test data table
'------------------------------------------------------------------

Public Function ColumnCount()
ColumnCount = UBound(mTestTable, 2)
End Function


' @Documentation Returns number of rows into the test data table
'---------------------------------------------------------------

Public Function RowCount()
RowCount = UBound(mTestTable, 1) - 1
End Function


2.4. Со стороны тестового скрипта

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


Dim TestArr() ‘Dynamic array
Dim TestD

Set TestD = CreateTestData()

Сall TestD.LoadFromStore("NamedRange", "C:\ExcelStore.xls")
Сall TestD.GetArrayFromStore(TestArr, "NamedRange", "C:\ExcelStore.xls")
‘Call TestD.GetArrayFromURL(TestArr, "OrgChart@"+ "C:\ExcelStore.xls")

Call TestD.SetData(TestArr)
Erase TestArr
Call TestD.GetData(TestArr)

Print TestArr(1,1)
Print TestD.GetCellByIndex(2,2)
Print TestD.GetCellByName("Name", 2)
Print TestD.RowCount
Print TestD.ColumnCount


Обращаю ваше внимание, что массив (если вы решите выгружать данные из TestData объекта) должен быть динамическим, а не статическим.

Для более глубокого понимания функционала предлагаю пройтись по нему в режиме отладки и внимательно проконтролировать весь процесс.

Вы также наверняка заметили одну закомментированную функцию, я имею в виду GetArrayFromURL.
Я использую данную функцию для удобной реализации вложенных данных. В этом случае на уровне Excel каждая строка должна содержать дополнительную колонку, в которой хранится URL связанного массива данных.



Предлагаю вам реализовать данную функциональность самостоятельно.


3. Выводы

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

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

С уважением,
Сергей Талалаев

С большой признательностью к моей коллеге Анне Валерьевне.

Read more...