воскресенье, 15 марта 2015 г.

GUI-testing 7. Briefly. About GUI-testing “in the spoken style”


Original in Russian: http://18delphi.blogspot.ru/2013/11/gui.html

GUI-testing. Table of contents

About the real implementation it is written here:
http://18delphi.blogspot.ru/2013/10/blog-post_7652.html
http://18delphi.blogspot.ru/2013/10/blog-post_7099.html .

Now, I’ll try to describe the concept.

Let us have a form:

TSomeForm = class(TForm)
 SomeButton : TButton;
end;//TSomeForm

Suppose we want to have a possibility to press button SomeButton on form SomeForm.
From our tests.

To do this, we can use the following test engine words:

interface
 
 TkwFindForm = class(TscriptKeyWord) 
 protected
  procedure DoIt(aContext : TscriptContext); override;
 end;//TkwFindForm
 
 TkwFindComponent = class(TscriptKeyWord)
 protected
  procedure DoIt(aContext : TscriptContext); override;
 end;//TkwFindComponent
 
 TkwButtonClick = class(TscriptKeyWord)
 protected
  procedure DoIt(aContext : TscriptContext); override;
 end;//TkwButtonClick

The implementation:

implementation
 
procedure TkwFindForm.DoIt(aContext : TscriptContext);
var
 l_Name : String;
 l_Form : TForm;
begin
 l_Name := aContext.PopString;
 Assert(l_Name <> '');
 l_Form := Screen.FindFormByName(l_Name); // - this method does not exist, but it can easily be written
 Assert(l_Form <> nil);
 aContext.PushObject(l_Form);
end;
 
procedure TkwFindComponent.DoIt(aContext : TscriptContext);
var
 l_Name : String;
 l_Form : TForm;
 l_Component : TComponent;
begin
 l_Name := aContext.PopString;
 l_Form := aContext.PopObject As TForm;
 Assert(l_Name <> '');
 Assert(l_Form <> nil);
 l_Component := l_Form.FindComponent(l_Name);
 Assert(l_Component <> nil);
 aContext.PushObject(l_Component);
end;
 
procedure TkwButtonClick.DoIt(aContext : TscriptContext);
var
 l_Component : TComponent;
begin
 l_Component := aContext.PopObject As TComponent;
 Assert(l_Component Is TButton);
 (l_Component As TButton).Click;
end;

We register the described words in test engine:

initialization
 ScriptEngine.RegisterWord(TkwFindForm, 'FindForm');
 ScriptEngine.RegisterWord(TkwFindComponent, 'FindComponent');
 ScriptEngine.RegisterWord(TkwButtonClick, 'ButtonCick');

It is obvious that words identifiers can be “created” from ClassName, but it is not important.

Now, we can write the first test:

VAR l_Form
VAR l_Button
'SomeForm' FindForm =: l_Form
l_Form 'SomeButton' FindComponent =: l_Button
l_Button ButtonClick

It does want we want from it.
(You shouldn’t be scary of the reverse Polish. I write like this because I’ve got it. Historically. The reverse Polish or infix notation – not a real problem)

But. I would like “in the spoken style”.

We’ll write “auxiliary” words, already on script language of test engine.

Suppose we know that SomeForm is a user registration form, and SomeButton is a button for saving.
It also comes from the business logic.

Let’s write:

CONST "Registration form" 'SomeForm'
CONST "Save" 'SomeButton'

Then, we can rewrite the test in this way:

VAR l_Form
VAR l_Button
" Registration form" FindForm =: l_Form
l_Form "Save" FindComponent =: l_Button
l_Button ButtonClick

Let’s move on.

We write:

STRING FUNCTION "Find the form" STRING IN aFormName
 aFormName FindForm =: Result
END //" Find the form"
 
STRING FUNCTION "Find find the component on the form" STRING IN aComponentName OBJECT IN aForm
 aForm aComponentName FindComponent =: Result
END //" Find find the component on the form""
 
PROCEDURE "Press the button" OBJECT IN aButton
 aButton ButtonClick
END //" Press the button"
 
WORDALIAS VAR Variable

Then, the test can be rewritten in this way:

Variable "Found form"
Variable " Found button"
"Find the form {("Registration form")}" =: "Found form"
"Find find the component {("Save")} on the form {("Found form")}" =: "Found button"
"Press the button {("Found button")}"

And the finishing touch.
We input the written word to the dictionary:

PROCEDURE "Press the button Save on registration form"
Variable "Found form"
Variable " Found button"
"Find the form {("Registration form")}" =: "Found form"
"Find find the component {("Save")} on the form {("Found form")}" =: "Found button"
"Press the button {("Found button")}"
END //"Press the button Save on registration form"

Now, test looks as follows:

"Press the button Save on registration form "

- all reserved structures – are "hidden" inside “high-level words” – “Press the button Save on registration form”.

It is no longer a “word”, but actually a full “sentence”.

The one that got into script engine dictionary and is taken as valid identifier by the script engine.
The one that starts to take part in scripts compilation process.

Why do we need it?

Of course, not to “write in the spoken style”. This is surely a utopia.

The idea is these tests can be “write and read in any language”.

Test resembles TestCase.

It can be run not only by the script machine, but a human being.

Finally – the “self-documenting” of the code.

Thus, by finding the required “handles” in Delphi (not necessarily through RTTI) and describing the “high-level” words in temporary dictionaries of the test engine – we can quickly “gain weight” we need to write tests of TestCase kind.

A bit about “how this all is organized inside” read here - http://18delphi.blogspot.com/2015/03/gui-testing-10-gui-testing-in-spoken.html

Комментариев нет:

Отправить комментарий