1.3 Добавление свойств (property) и методов (method)

Назад Содержание Дальше

1.3.1 Свойства (properties)

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

  • использовать метод SetText ()
  • использовать свойство sValue

Например, следующие две строки выполнят одно и то же: занесут заданную строку “Text” в поле ввода Field, которое находится в окне Dialog:

  • Dialog.Field.SetText (“Text”)
  • Dialog.Field.sValue = “Text”

Кроме того, можно воспользоваться общим для всех окон методом TypeKeys:
Dialog.Field.TypeKeys (“Text”)

Точно также можно работать и с другими элементами управления. Например, для элемента RadioList можно использовать метод Select() или одно из свойств: sValue, iValue.

На самом деле встроенными являются лишь методы, а свойства (iValue, sValue и т.д.) определены средствами SilkTest-а в файле winclass.inc.

Точно так же можно описывать свои свойства, которые могут пригодиться в работе.
У свойств могут быть 2 метода: Set() и Get(). Первый предназначен для установки значения, второй – для его (значения) извлечения.

Например, имеем следующее описание объекта в диалоговом окне:

Code

[-] window DialogBox dDialog 
	[ ] tag "#1"
	[-] TextField edtField
		[ ] tag "#1"

 

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

Code

[-] property sField
	[-] STRING Get ()
		[ ] return this.edtField.sValue
	[-] VOID Set (STRING sValue)
		[ ] this.edtField.sValue = sValue

Поместить объявление этого свойства необходимо на одном уровне с полем edtField.

Теперь работа с этим полем немного упростилась:

  • чтобы ввести значение, необходимо написать dDialog.sField = “Text” (сравните со стандартным dDialog.edtField.sValue = “Text” или dDialog.edtField.SetText(“Text”) )
  • чтобы извлечь значение, необходимо написать STRING sData = dDialog.sField (сравните со стандартным STRING sData = dDialog.edtField.sValue или STRING sData = dDialog.edtField.GetText() ).

Это очень простой пример, однако могут встречаться и случаи сложнее.

 

Пример из практики: в приложении было текстовое поле с несколькими символами в нем, каждый из которых обозначал какую-то настройку. Каждый из символов влиял на функциональность всего приложения. Извлечь их было очень просто, стандартными методами SilkTest-а, а вот записать строку в это поле невозможно: строка была доступна только для чтения, а для изменения строки в этом поле служило диалоговое окно с кучей CheckBox’ов в нем. Если CheckBox включен – соответствующий символ появляется в строке. Это дополнительное окно открывалось по нажатию на кнопку рядом с полем ввода. Естественно, что каждый раз писать код для открытия этого окна и изменения значений CheckBox’ов не имеет смысла. Поэтому было описано новое свойство. Метод Get() для него был простой: использовался стандартный метод GetText(); а вот метод Set() был посложнее: он принимал строку символов, нажимал на кнопку, в диалоговом окне заполнял требуемые данные, после чего закрывал окно. Написать этот метод Set() было ненамного сложнее, чем написать эти же действия для какого-то конкретного случая, а экономия времени в дальнейшем велика: вместо кучи действий использовалось всего одно присваивание.

В качестве примера посмотрите на свойство lsListView в окне dListView (файл TestApp.inc) и тесткейс Using_Properties (файл TestApp.t).

  1. Попробуйте расширить это свойство, чтобы вместо того, чтобы создавать колонку с заголовком Column, метод Set() принимал бы и имя колонки (подсказка: так как параметр у метода Set() может быть лишь один, воспользуйтесь созданием нового типа). Если на данном этапе задание кажется вам сложным – попробуйте вернуться к нему позже.
  2. Придумайте и напишите подобное свойство для другого окна.

 

1.3.2 Аттрибуты (attribute)

Аттрибуты ассоциируются с оконным классом (НЕ окном!) и используются методами GetEverything и VerifyEverything для получения и проверки информации в окне. Для стандартных классов аттрибуты определены в файле winclass.inc.
Кроме того, можно добавлять аттрибуты, определяемые пользователем.

Общий вид объявления аттрибута:

Code

attribute sAttribute, VerifyFunc, GetFunc

где:

  • sAttribute – имя аттрибута
  • VerifyFunc – имя функции, которая используется для проверки значения этого аттрибута
  • GetFunc – имя функции, используемой для получения значения аттрибута

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

 

Code

	[ ] attribute "Number of children", VerifyNumChild, GetNumChild
	[-] INTEGER GetNumChild() 
		[ ] return ListCount (this.GetChildren ()) // return count of children of dialog
	[-] hidecalls VerifyNumChild (integer iExpectedNum)
		[ ] Verify (this.GetNumChild (), iExpectedNum, "Child number test")

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

В файле TestApp.t есть тесткейс Using_Attributes, который демонстрирует использование аттрибутов для окна dCheckBox.

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

1.3.3 Методы (Methods)

Метод – это функция, определенная для конкретного окна или винкласса. Общий вид описания метода выглядит так:

Code

[gui-specifier] [return-type] method-id ( [arguments])

gui-specifier – определяет область видимости (private или public) метода
return-type – значение, возвращаемое методом; если не указано, то метод не возвращает никакого значения
method-id – имя метода
arguments – аргументы, передаваемые методу

Имя метода должно быть уникальным для данного класса и/или окна. Если у вас объявлен винкласс и окно этого класса, то методы можно объявлять как внутри класса, так и внутри окна. Однако желательно придерживаться какого-то одного стиля во избежание путаницы и упрощения поиска.

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

Например, для окна wTestApp определен метод CloseAll(), закрывающий все окна этого приложения, кроме главного. Вызов этого метода будет выглядеть так:

Code

wTestApp.CloseAll()

 

Однако, учитывая вышесказанное, мы можем написать следующее:

Code

wTestApp.File.New.CloseAll()

Такой код отработает нормально в том случае, если внутри нет обращений к каким-либо объектам главного окна, которые не определены для пункта меню File – New (например, при попытке таким же образом вызвать метод AddMenu() возникнет ошибка, так как данный метод использует элемент MenuBar. который для пункта меню не определен). SilkTest, начиная с версии 7.0, в подобных случаях при компиляции выдает предупреждение:
*** Warning: Function CloseAll is not defined for window wTestApp.File.New

Однако все равно отрабатывает. Естественно, что делать так категорически не рекомендуется.

Виртуальные методы

В некоторых случаях вам может потребоваться объявить метод в классе, который потом будет переопределяться его потомками. Такой метод называется виртуальным (аналогичен виртуальным методам в с++). Для объявления виртуального метода необходимо в самом начале его объявления поставить ключевое слово virtual:

Code

virtual void MyMethod ()

После чего его можно переопределять в дочерних классах.

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

Code

derived::MyMethod()

В данном случае будет вызван метод предка.

В качестве примера рассмотрите тесткейс Virtual_Methods_Demonstration из файла TestApp.t и переопределенные методы окон, которые в нем используются, из файла TestApp.inc.
В этом примере рассмотрены следующие возможности:

  1. Для класса TestApp_Controls (общего класса для практически всех окон, которые вызываются из меню Control) переопределен стандартный метод Close(). Он переопределен таким образом, чтобы для закрытия окна вызывать стандартный метод Close(), если параметр bUseDerived установлен в TRUE, или нажимать на кнопку Exit в остальных случаях (когда параметр bUseDerived не установлен или равен FALSE). Первый случай вызывается в примере 1, второй случай – в примере 4.
  2. Для окна dListView метод Close() снова переопределен таким образом, чтобы нажимать комбинацию клавиш Alt-E для закрытия окна. Этот метод используется в примере 2.
  3. В примере 3 для окна dPageList определен таким образом, чтобы вызывать метод предка (derived). Так как это окно наследуется от класса TestApp_Controls, соответсвенно вызывается метод этого класса.

 

Кроме того здесь показан пример, как использовать опциональные (необязательные) аргументы в функциях. Конструкция, которая используется в методе Close() винкласса:

Code

[-] virtual void Close (BOOLEAN bUseDerived NULL optional)
	[-] if (IsNull (bUseDerived) || !bUseDerived)
		[ ] Print ("Pressing button Exit to close dialog")
		[ ] this.btnExit.Click ()
	[-] else
		[ ] Print ("Using standard Close() method")
		[ ] derived::Close ()

В первой строке при указании параметров мы говорим, что это опциональный параметр (ключевое слово optional) и может быть равен NULL. Затем в самом методе делаем проверку: Если параметр не передан или передан NULL (IsNull (bUseDerived)) либо ( || ) равен FALSE (!bUseDerived), то выполняется первая часть: нажатие на кнопку. Если ни одно из этих условий не выполнилось (то есть передан параметр TRUE), то вызывается изначальный метод Close().

В качестве самостоятельного задания рекомендуется следующее: переопределите для главного окна wTestApp метод Close() таким образом, чтобы он сначала вызывал метод CloseAll(), а затем закрывал само окно с помощью вызова метода предка.


Назад Содержание Дальше