For any form of automated testing is an integral part of an informative display the results as not enough just to make the run, you need more and be able to interpret the results. Consider the solution of this problem on the example of SilkTest.
For some reason, the standard output file is little suits. This can be attributed to such factors as:
The list is endless.
Consider the approach to the organization of the output. Consider the conclusion in a text format, since this is the most frequent case of the use of its system output. More concretely the problem: we need to conclude the results in HTML-format. That is, the startup script we have created a HTML-file and in the course of code execution, this file is filled with information.
So, since our conclusion is actually a duplicate standard output, then nothing wrong will not, if we make the replacements to the functions file output results. But to begin with, we consider the standard output functions:
That is, for these functions can do their counterparts. But unlike the standard functions, we require the functionality operates with another attribute – the name of the file that will be recorded. That is, these functions are analogues and an attribute name of the file tied to each other. Moreover, the file must be available to function prototypes, but is not available anywhere else. This fully complies with the standard features, as during script execution, we can not change the file that displays the results. The most appropriate solution for this problem is the class. If we turn to the practice in other media functional testing, in the same TestComplete is such an object as Log, which is responsible for the output to a log file. You can apply a similar principle.
So we need to create a class, or rather winclass, who will be responsible for the functionality of our input-output. Also, we need a global variable is an instance of this class. To do this we will create a separate file, call it MyLogger.inc and start inscribe lines
[ ] private STRING sFileName
2[ ] window MyLoggerClass Log
3[ ]
4[+] winclass MyLoggerClass
5 [ ]
As a result of this method, all arguments passed to the method will be glued to the string. This line will be placed inside the structure <font face="Tahoma" color="Black"> …</ font> and subsequently written to the file, and this line complements the existing file or creates a new file if the file name sFileName yet.
Go ahead. Analogue of ListPrint implemented using the method of Message. Thus, the implementation of this method is as follows:
[+] winclass MyLoggerClass
2 [ ]
3 ………………………………………………………
4 [+] VOID ListPrint( LIST OF ANYTYPE laValue )
5 [ ] ANYTYPE aValue
6 [ ]
7 [+] for each aValue in laValue
8 [ ] this.Message(aValue)[] This.Message (aValue)
Now, we realize the method, analog functions LogWarning. It will give the file a message, highlighted color code FF00FF. This is the default color for warnings SilkTeste. The code is as follows:
[+] winclass MyLoggerClass
2 [ ]
3 ………………………………………………………
4 [+] VOID Warning( STRING sWarning )
5 [ ] LogWarning( sWarning )
6 [ ] this._writeFile( "<br><font face=""Tahoma"" color=#FF00FF>{sWarning}</font>" )
Now, by analogy we make a wrapper for LogError with one small correction: the error can be critical (must immediately withdraw from testkeysa) and uncritical (you can continue to perform testkeysa). This can take into account additional parameters responsible for criticality. The code is as follows:
[+] winclass MyLoggerClass
02 [ ]
03 ………………………………………………………
04 [+] VOID Error( STRING sError , BOOLEAN bCritical optional )
05 [ ] LogError( sError )
06 [ ]
07 [ ] this._writeFile( "<br><font face=""Tahoma"" color=#FF0000>{sError}</font>" )
08 [ ]
09 [+] if( !IsNull( bCritical ) && bCritical )
10 [ ] raise -1 , sError
By default, calling this method raises no exceptions, but in any case writes to a file string errors highlighted in red. And the last method is a method that gives information about the thrown. Method looks like this:
[+] winclass MyLoggerClass
02 [ ]
03 ………………………………………………………
04 [+] VOID ExceptWrite()
05 [ ] CALL_LIST lpCalls
06 [ ] CALL pCall
07 [ ]
08 [ ] ExceptPrint()
09 [ ]
10 [ ] lpCalls = ExceptCalls()
11 [ ] pCall = lpCalls[1]
12 [ ] this.Message( "{ExceptData()}" )
13 [ ] this.Message("Occured in {pCall.sFunction} {pCall.sModule} ({pCall.iLine})")
14 [ ] ListDelete(lpCalls,1)
15 [ ]
16 [+] for each pCall in lpCalls
17 [ ] this.Message("Called from {pCall.sFunction} {pCall.sModule} ({pCall.iLine})")
Now, a little makeup. We need to somehow note that testkeys started running and finished it. To do this,’s update the 2 methods (we will not bother until the details, the main thing – it is a principle):
[+] winclass MyLoggerClass
02 [ ]
03 ………………………………………………………
04 [+] VOID StartTC()
05 [ ] this._writeFile("<br><h1>Test case: {GetTestCaseName()}</h1>")
06 [ ]
07 [+] VOID StopTC( BOOLEAN bException )
08 [+] if( bException )
09 [ ] this.Error("Exception: {ExceptData()}")
10 [ ] this.ExceptWrite()
11 [ ] ExceptClear()
12 [ ] this.Message("<br>Test case <b>{GetTestCaseName()}</b> is completed")
While we will not go into details as to why these methods have such a form. We assume that it should be.
It seems that almost everything, but not quite. We also need to set sFileName, but it is not very accessible from the outside. In this class we add a method that initializes the variable. It looks like this:
[+] winclass MyLoggerClass
2 [ ]
3 ………………………………………………………
4 [+] VOID Init()
5 [ ] sFileName = "{GetProgramDir()}"Report_{FormatDateTime(GetDateTime(),"yyyymmddhhnnss")}.htm"
In this case, explicitly specify the current directory where the file is a script, but you can specify another way, including by setting it explicitly. The most important thing – the file name is generated dynamically using as part of a unique name for the current date and time.
All the class is ready. Now let us adapt it to the system. Object through which we interact with the system through an object Log – instance MyLoggerClass. This instance, we have created in the beginning.
We proceed to the next stage. We need to get at each startup script (regardless of whether they were there testkeysy or not), our results file created (you need to call Init). At the outset of testkeysa we need to call StartTC, and at the end – StopTC, so that the necessary requisites testkeysa been made to the results file.
To do this we need to bring recovery-system. What is it and why you eat, you can read in the book Guide to Borland SilkTest in the third chapter. In this case, we need a function:
ScriptEnter – start immediately before the first testkeysom the current script file
ScriptExit – starts immediately after the last testkeysa the current script file
TestCaseEnter – runs directly in front of each testkeysom
TestCaseExit – run after each testkeysa
In principle, these functions we can describe explicitly in the current file, in which described the class. But such a function rather specific to the project, rather than for the class. A class that is just more or less common. Accordingly, next to the file MyLogger.inc Recovery.inc create a file with the following contents:
[ ] use "MyLogger.inc"
02[ ]
03[+] ScriptEnter()
04 [ ] Log.Init()
05 [ ] DefaultScriptEnter()
06[ ]
07[+] ScriptExit( BOOLEAN bException )
08 [+] if( bException )
09 [ ] Log.ExceptWrite()
10 [ ] DefaultScriptExit( bException )
11[ ]
12[+] TestCaseEnter()
13 [ ] Log.StartTC()
14 [ ] DefaultTestCaseEnter()
15[ ]
16[+] TestCaseExit( BOOLEAN bException )
17 [ ] Log.StopTC( bException )
18 [ ] DefaultTestCaseExit( bException )
That’s it. Now it remains in your scripts to connect this particular file Recovery.inc (if you’re doing some other action in the functions of recovery-system, then add them to the file where you want to) and instead of the usual Print, ListPrint, LogWarning, LogError, ExceptPrint use respectively Log.Message, Log.ListPrint, Log.Warning, Log.Error.
After each run the script in a directory that is specified in the Init method will create a new file containing the results of the script.