QTP 10 Version - Patches
Hi ,
In view of the given below, HP introduced the corresponding Patches for Quick Test Pro 10 V.
- Support Stingray Studio 10.0/1 MFC8/9
- Recognize SilverLight 2.0 App with SilverLight 3.0 Plug-in
- Improve Performance on Siebel Apps
- Stability Fixes for QTP Debug Viewer
- Do Not Filter Invisible Windows
- Fix Exist When Used With ChildObjects
- Improve QTP Folder Browsing Speed
- Fix Corrupted File Causing QTP Crash
- Support for Internet Explorer 8
- New QuickTest Silverlight Add-in
- Silverlight Support for QC Add-in
- Fix Debug Viewer Problems with PDM
- Prevent Unexpected Icons in Big Tests
- Fix Rec Scenario Function Library Display in QC
- Add Recovery Scenario Function Library Dependency
- Add Support for PowerBuilder 11.5
- Support VisualAge Smalltalk 7.5
- Support Stingray Studio 10.0/1
- Allow RegEx's in WPF Properties
- Support Windows 7 and Server 2008 R2 (Patch :QTP_00644)
In view of the given below, HP introduced the corresponding Patches for Quick Test Pro 10 V.
- Support Stingray Studio 10.0/1 MFC8/9
- Recognize SilverLight 2.0 App with SilverLight 3.0 Plug-in
- Improve Performance on Siebel Apps
- Stability Fixes for QTP Debug Viewer
- Do Not Filter Invisible Windows
- Fix Exist When Used With ChildObjects
- Improve QTP Folder Browsing Speed
- Fix Corrupted File Causing QTP Crash
- Support for Internet Explorer 8
- New QuickTest Silverlight Add-in
- Silverlight Support for QC Add-in
- Fix Debug Viewer Problems with PDM
- Prevent Unexpected Icons in Big Tests
- Fix Rec Scenario Function Library Display in QC
- Add Recovery Scenario Function Library Dependency
- Add Support for PowerBuilder 11.5
- Support VisualAge Smalltalk 7.5
- Support Stingray Studio 10.0/1
- Allow RegEx's in WPF Properties
- Support Windows 7 and Server 2008 R2 (Patch :QTP_00644)
Script to Upload Attachment To QC
Hi All,
Here I am providing the way of uploading an attachment into Quality Center programmatically using "QC OTA" API.
Note: QuickTest should be connected to a Quality Center server before executing below code.
Dim ObjCurrentTest,ObjAttch
Set ObjCurrentTest = QCUtil.CurrentTest.Attachments
Set ObjAttch = ObjCurrentTest.AddItem(Null)
ObjAttch.FileName = "C:\...\SampleTestResults.xls"
ObjAttch.Type = 1
ObjAttch.Post
ObjAttch.Refresh
After the above execution, 'xls' file would be attached to current Testscript 'Attachments' Section in QC.
Here I am providing the way of uploading an attachment into Quality Center programmatically using "QC OTA" API.
Note: QuickTest should be connected to a Quality Center server before executing below code.
Dim ObjCurrentTest,ObjAttch
Set ObjCurrentTest = QCUtil.CurrentTest.Attachments
Set ObjAttch = ObjCurrentTest.AddItem(Null)
ObjAttch.FileName = "C:\...\SampleTestResults.xls"
ObjAttch.Type = 1
ObjAttch.Post
ObjAttch.Refresh
After the above execution, 'xls' file would be attached to current Testscript 'Attachments' Section in QC.
Retrieve Field/column count of Database Table
Hi ,
Here is the script for finding the number of fields/columns of a Table in MS Access Database.
Code:
Dim db
Set db=createobject("ADODB.Connection")x.ConnectionString="DBQ=C:\PROGRAM FILES\HP\QuickTest Professional\samples\flight\app\flight32.mdb;DefaultDir=C:\PROGRAM FILES\HP\QuickTest Professional\samples\flight\app;Driver={Microsoft Access Driver (*.mdb)};DriverId=281;FIL=MS Access;FILEDSN=C:\Program Files\Common Files\ODBC\Data Sources\flight32.dsn;MaxBufferSize=2048;MaxScanRows=8;PageTimeout=5;SafeTransactions=0;Threads=3;UID=admin;UserCommitSync=Yes;"
db.open
Set RecordSet=db.Execute("Select * from orders")
Set r= RecordSet.fields
msgbox r.count ' Number of the columns in the table 'ORDERS'
For i=0 to r.count-1
msgbox r(i).name ' name of the field/column
Next
db.close
Set db=nothing
Here is the script for finding the number of fields/columns of a Table in MS Access Database.
Code:
Dim db
Set db=createobject("ADODB.Connection")x.ConnectionString="DBQ=C:\PROGRAM FILES\HP\QuickTest Professional\samples\flight\app\flight32.mdb;DefaultDir=C:\PROGRAM FILES\HP\QuickTest Professional\samples\flight\app;Driver={Microsoft Access Driver (*.mdb)};DriverId=281;FIL=MS Access;FILEDSN=C:\Program Files\Common Files\ODBC\Data Sources\flight32.dsn;MaxBufferSize=2048;MaxScanRows=8;PageTimeout=5;SafeTransactions=0;Threads=3;UID=admin;UserCommitSync=Yes;"
db.open
Set RecordSet=db.Execute("Select * from orders")
Set r= RecordSet.fields
msgbox r.count ' Number of the columns in the table 'ORDERS'
For i=0 to r.count-1
msgbox r(i).name ' name of the field/column
Next
db.close
Set db=nothing
Import Data from Database Table to Datatable
Hi ,
Here is the script for importing the data from a specific column of MS Access Database Table to Datatable's GlobalSheet.
Code :
Dim db
Set db=CreateObject("ADODB.Connection")
db.connectionString="DBQ=C:\PROGRAM FILES\HP\QuickTest Professional\samples\flight\app\flight32.mdb;DefaultDir=C:\PROGRAM FILES\HP\QuickTest Professional\samples\flight\app;Driver={Microsoft Access Driver (*.mdb)};DriverId=281;FIL=MS Access;FILEDSN=C:\Program Files\Common Files\ODBC\Data Sources\flight32.dsn;MaxBufferSize=2048;MaxScanRows=8;PageTimeout=5;SafeTransactions=0;Threads=3;UID=admin;UserCommitSync=Yes;"
db.Open
Set RecordSet=db.Execute("Select * from Orders")
i=1
While (NOT recordset.EOF)
Datatable.SetCurrentRow(i)
Datatable("CustomerName",dtGlobalSheet)=Recordset.Fields("Customer_Name")
msgbox Datatable("CustomerName",dtGlobalSheet)
Recordset.MoveNext
i=i+1
Wend
db.Close
Set db=Nothing
Here is the script for importing the data from a specific column of MS Access Database Table to Datatable's GlobalSheet.
Code :
Dim db
Set db=CreateObject("ADODB.Connection")
db.connectionString="DBQ=C:\PROGRAM FILES\HP\QuickTest Professional\samples\flight\app\flight32.mdb;DefaultDir=C:\PROGRAM FILES\HP\QuickTest Professional\samples\flight\app;Driver={Microsoft Access Driver (*.mdb)};DriverId=281;FIL=MS Access;FILEDSN=C:\Program Files\Common Files\ODBC\Data Sources\flight32.dsn;MaxBufferSize=2048;MaxScanRows=8;PageTimeout=5;SafeTransactions=0;Threads=3;UID=admin;UserCommitSync=Yes;"
db.Open
Set RecordSet=db.Execute("Select * from Orders")
i=1
While (NOT recordset.EOF)
Datatable.SetCurrentRow(i)
Datatable("CustomerName",dtGlobalSheet)=Recordset.Fields("Customer_Name")
msgbox Datatable("CustomerName",dtGlobalSheet)
Recordset.MoveNext
i=i+1
Wend
db.Close
Set db=Nothing
QTP script to Add defect in QC
Hi ,
Most of us would be familiar with logging defects in Quality Center manually.
How about Adding a defect using a QTP script?
Here we go !!!
Script :
Set TDConnection = CreateObject(”TDApiOle.TDConnection”)
TDConnection.InitConnection “http://yovav/tdbin” ‘ DB URL
TDConnection.ConnectProject “TD76″,”bella”,”pino” ‘ Valid login information
If TDConnection.Connected Then
MsgBox(”Connected to ” + chr (13) + “Server ” + TDConnection.ServerName _+ chr (13) +”Project ” + TDConnection.ProjectName )
Else
MsgBox(”Not Connected”)
End If
‘Get the IBugFactory
Set BugFactory = TDConnection.BugFactory
‘Add a new empty bug
Set Bug = BugFactory.AddItem (Nothing)
‘fill the bug with relevant parametersBug.Status = “New”
Bug.Summary = “Connecting to TD”
Bug.Priority = “4-Very High” ‘ depends on the DB
Bug.AssignedTo = “admin” ‘ user that must exist in the DB’s users list
Bug.DetectedBy = “admin” ‘ user that must exist in the DB’s users list
‘Post the bug to DB ( commit )
Bug.Post
Most of us would be familiar with logging defects in Quality Center manually.
How about Adding a defect using a QTP script?
Here we go !!!
Script :
Set TDConnection = CreateObject(”TDApiOle.TDConnection”)
TDConnection.InitConnection “http://yovav/tdbin” ‘ DB URL
TDConnection.ConnectProject “TD76″,”bella”,”pino” ‘ Valid login information
If TDConnection.Connected Then
MsgBox(”Connected to ” + chr (13) + “Server ” + TDConnection.ServerName _+ chr (13) +”Project ” + TDConnection.ProjectName )
Else
MsgBox(”Not Connected”)
End If
‘Get the IBugFactory
Set BugFactory = TDConnection.BugFactory
‘Add a new empty bug
Set Bug = BugFactory.AddItem (Nothing)
‘fill the bug with relevant parametersBug.Status = “New”
Bug.Summary = “Connecting to TD”
Bug.Priority = “4-Very High” ‘ depends on the DB
Bug.AssignedTo = “admin” ‘ user that must exist in the DB’s users list
Bug.DetectedBy = “admin” ‘ user that must exist in the DB’s users list
‘Post the bug to DB ( commit )
Bug.Post
Vital points to remember about Virtual Objects
Hi All,
Below are the important points which need to be noticed by us prior to using Virtual Objects in QTP.
Important Points :
1. A group of Virtual Objects are stored in Virtual Object Manager under a descriptive name known as “Virtual Object Collection”.
2. Analog & Low-level recording on Virtual Objects is not supported by QTP.
3. Recognition of Virtual Objects can be disabled without deleting them from Virtual Object Manager.
4. Virtual Objects can only be used when recording & Running the tests. Any type of checkpoint on a virtual object cannot be inserted.
5. The Virtual Object Collections shown in the Virtual Object Manager are stored in our computer (where they are created) and not in the tests that include the virtual object steps. This means that if you the virtual object in a script, the object will be recognized during the run session only if it is run on the computer containing the appropriate Virtual Object Definition. To Copy your virtual object definitions to another computer, copy the contents of your \Dat\VoTemplate folder (or individual collection files within this folder) to the same location on the destination computer.
6. Virtual Objects can only be defined for objects on which you can click or Dbl click and that record a click or Dbl click operation. Otherwise, the virtual object is ignored. For example, if you define a virtual Object manager over the WinList object, the “Select” operation is recorded, and the virtual Object operation is ignored.
7. You cannot use the Object Spy to view the properties of Virtual Object.
Below are the important points which need to be noticed by us prior to using Virtual Objects in QTP.
Important Points :
1. A group of Virtual Objects are stored in Virtual Object Manager under a descriptive name known as “Virtual Object Collection”.
2. Analog & Low-level recording on Virtual Objects is not supported by QTP.
3. Recognition of Virtual Objects can be disabled without deleting them from Virtual Object Manager.
4. Virtual Objects can only be used when recording & Running the tests. Any type of checkpoint on a virtual object cannot be inserted.
5. The Virtual Object Collections shown in the Virtual Object Manager are stored in our computer (where they are created) and not in the tests that include the virtual object steps. This means that if you the virtual object in a script, the object will be recognized during the run session only if it is run on the computer containing the appropriate Virtual Object Definition. To Copy your virtual object definitions to another computer, copy the contents of your \Dat\VoTemplate folder (or individual collection files within this folder) to the same location on the destination computer.
6. Virtual Objects can only be defined for objects on which you can click or Dbl click and that record a click or Dbl click operation. Otherwise, the virtual object is ignored. For example, if you define a virtual Object manager over the WinList object, the “Select” operation is recorded, and the virtual Object operation is ignored.
7. You cannot use the Object Spy to view the properties of Virtual Object.
Few Enhancements need to be incorporated in QTP
Hi ,
Many times people tend to ask what Limitations does QTP has.
Now it is very difficult for one to list out clear limitations of a tool but it is far more easier for one to point the enhancements required.
With now over 5 years of experience from QTP 8 to QTP 10, thought of highlighting all the enhancements that we could think of.
Lets hope HP would look at few of these seriously and incorporate them in upcoming version of QTP. :):):)
In case you can think of other enhancements that can be included in the below then do let us know .
Object Spy Enhancements :
1. Object spy to have an option to export all the objects in hierarchy with their properties and methods to a XLS/XML file. And also to have an option to reload this offline. This feature would help for others to analyze a object recognition remotely
2. Object spy to have the ability to run without QTP. Currently object spy can only be loaded through QTP
3. Object spy to have an option to disable the Auto spy. Currently hovering on any object displays it properties without the need to click the object. This at time gives poor performance while spying objects
4. Currently Object Spy button gets disabled when the script is run, one has to launch object repository and then launch Object Spy from there. The Object Spy should enable directly when the script is run
5. Object Spy Automation capability, so other tools can leverage the same and automate the OR creation based on custom rules
IDE Enhancement
6. Ability to open multiple scripts at one time
7. Project explorer with capability to create folder and organize library files in them
8. Improved Intellisense for objects created through DotNetFactory
9. Intellisense for VBScript classes
10. Function folding in the IDE
11. Transition from Design mode to Run mode causes too many flickers in the IDE UI. This needs to be smooth
12. Ability to view code for Test flow in Expert view. This is currently only possible through Keyword view
13. Design time non-syntax error check for issues like Duplicate variable declaration etc
14. Intellisense of current associated libraries in all Libraries. Currently if Lib1 and Lib2 are associated with a Test. The Lib1 will only show Intellisense for Lib1 and not for Lib2. The Test will show Intellisense for both Lib1 and Lib2. This creates difficulty when Lib2 functions need to be called in Lib1
Object Repository Enhancements :
15. Ability to create and load OR’s from QTP script itself
16. Ability to load Shared ORs dynamically to all the Actions. Currently RepositoriesCollection.Add methods adds the SOR to the current Action only and not other actions
17. Changes made through SetTOProperty in one Action does not get propagated to Next Action
18. Ability to enumerate all child objects present in the OR for a specified object
19. Ability to specify nickname for Objects. This would help get a complete object hierarchy through just the nick name
Object Repository Manager Enhancements
20. Ability to load and save directly to OR in XML format
21. Ability for multiple users to access the Shared OR at the same time for updating
22. Export/Import of Checkpoints from one SOR to another
23. Merging of SOR’s to an existing SOR. Currently when two SOR are merged, the merged SOR needs to be saved as a different file
24. Ability to update code when conflict resolution renames object during SOR merge. In case object A and B are merged and name A is chosen over B, all scripts using name B needs to be updated manually
Scripting Enhancements
25. More options for other scripting languages i.e. JScript, VB.NET, C#.NET etc…
26. Support for start and finish events in Action and Test. E.g. – Test_Init, Test_Terminate, Action_Init, Action_Terminate. Currently this can be achieved through use of class but it would be easier for people to use if the functionality is built-in
27. Ability to execute specified VBScript even before the test execution starts. This script would run outside QTP and would help make changes to QTP settings that cannot be done during run-time. This would help in overcoming limitations like Libraries cannot be associated at run-time
28. Ability to execute specified VBScript even after the test execution starts. This script would run outside QTP and would help perform post execution code. This would be helpful in scenarios like sending email with the report
29. Ability to create error handler functions which are automatically called when an error occurs
30. Performance improvement when using Descriptive programming when compared to Object Repository usage
31. Ability to Debug libraries loaded during run-time using Execute, ExecuteGlobal and ExecuteFile
32. Ability to register generic functions for any object type. Currently RegisterUserFunc can only be used to register the method for a single object type. So if a new Set method is created then multiple RegisterUserFunc statements need to be written. QTP should provided some way to use a pattern or something to apply the same method to multiple object types
33. Ability to Unlock a locked system from within the code34. Ability to prevent screen locking during the execution
35. Ability to debug error which occurs during terminations of script. Currently any errors that occur during the termination of the script cannot be debugged and launches.
Recovery Scenarios Enhancements:
36. Recovery scenarios (RS) to run in a separate thread. Currently recovery scenarios run in the same thread as QTP. This causes recovery scenarios to be useless in case a Modal dialog blocks QTP
37. Option to stop chaining in recovery scenarios. Currently if RS1 and RS2 both match the trigger criteria then both of the scenarios are executed. There is no way to specify that RS2 should not be executed if RS1 is executed
38. Currently there is no way to enumerate recovery scenarios present in a File
39. Recovery scenarios don’t work when they are associated at run-time
Test Reporting Enhancements:
40. Ability to create reports in different format. Excel, Word, HTML etc…
41. Reporting of errors or failure in different categories and priority. E.g. – Reporting a error with severity, priority and category (Application, Script, Validation, Checkpoint)
42. Exact location of the error in the script. This should include the line of code, error number, error statement
43. Direct ability to send report to a specified list of email addresses when the test end
44. Currently the reports can only be viewed through QTP reporter viewer and cannot be viewed on machines without this tool. Report should be made completely Web compatible so that I can be viewed in any browser in the same way it is displayed in report viewer
45. Ability to view status of current Action. Currently Reporter.RunStatus only provides the status of whole test and not for current action
46. Ability to enumerate the current status from within a Test i.e. Actions executed with details, checkpoints executed with details, recovery scenarios executed with details
Checkpoint Enhancements:
47. Ability to alter properties of all checkpoints during run-time. E.g. Expected bitmap of a bitmap checkpoint, expected values of a Table/DB checkpoint etc
48. Ability to create checkpoints at run-time
49. Ability to load checkpoints from a external file at run-time
50. Ability to enumerate all checkpoints present in current script
Many times people tend to ask what Limitations does QTP has.
Now it is very difficult for one to list out clear limitations of a tool but it is far more easier for one to point the enhancements required.
With now over 5 years of experience from QTP 8 to QTP 10, thought of highlighting all the enhancements that we could think of.
Lets hope HP would look at few of these seriously and incorporate them in upcoming version of QTP. :):):)
In case you can think of other enhancements that can be included in the below then do let us know .
Object Spy Enhancements :
1. Object spy to have an option to export all the objects in hierarchy with their properties and methods to a XLS/XML file. And also to have an option to reload this offline. This feature would help for others to analyze a object recognition remotely
2. Object spy to have the ability to run without QTP. Currently object spy can only be loaded through QTP
3. Object spy to have an option to disable the Auto spy. Currently hovering on any object displays it properties without the need to click the object. This at time gives poor performance while spying objects
4. Currently Object Spy button gets disabled when the script is run, one has to launch object repository and then launch Object Spy from there. The Object Spy should enable directly when the script is run
5. Object Spy Automation capability, so other tools can leverage the same and automate the OR creation based on custom rules
IDE Enhancement
6. Ability to open multiple scripts at one time
7. Project explorer with capability to create folder and organize library files in them
8. Improved Intellisense for objects created through DotNetFactory
9. Intellisense for VBScript classes
10. Function folding in the IDE
11. Transition from Design mode to Run mode causes too many flickers in the IDE UI. This needs to be smooth
12. Ability to view code for Test flow in Expert view. This is currently only possible through Keyword view
13. Design time non-syntax error check for issues like Duplicate variable declaration etc
14. Intellisense of current associated libraries in all Libraries. Currently if Lib1 and Lib2 are associated with a Test. The Lib1 will only show Intellisense for Lib1 and not for Lib2. The Test will show Intellisense for both Lib1 and Lib2. This creates difficulty when Lib2 functions need to be called in Lib1
Object Repository Enhancements :
15. Ability to create and load OR’s from QTP script itself
16. Ability to load Shared ORs dynamically to all the Actions. Currently RepositoriesCollection.Add methods adds the SOR to the current Action only and not other actions
17. Changes made through SetTOProperty in one Action does not get propagated to Next Action
18. Ability to enumerate all child objects present in the OR for a specified object
19. Ability to specify nickname for Objects. This would help get a complete object hierarchy through just the nick name
Object Repository Manager Enhancements
20. Ability to load and save directly to OR in XML format
21. Ability for multiple users to access the Shared OR at the same time for updating
22. Export/Import of Checkpoints from one SOR to another
23. Merging of SOR’s to an existing SOR. Currently when two SOR are merged, the merged SOR needs to be saved as a different file
24. Ability to update code when conflict resolution renames object during SOR merge. In case object A and B are merged and name A is chosen over B, all scripts using name B needs to be updated manually
Scripting Enhancements
25. More options for other scripting languages i.e. JScript, VB.NET, C#.NET etc…
26. Support for start and finish events in Action and Test. E.g. – Test_Init, Test_Terminate, Action_Init, Action_Terminate. Currently this can be achieved through use of class but it would be easier for people to use if the functionality is built-in
27. Ability to execute specified VBScript even before the test execution starts. This script would run outside QTP and would help make changes to QTP settings that cannot be done during run-time. This would help in overcoming limitations like Libraries cannot be associated at run-time
28. Ability to execute specified VBScript even after the test execution starts. This script would run outside QTP and would help perform post execution code. This would be helpful in scenarios like sending email with the report
29. Ability to create error handler functions which are automatically called when an error occurs
30. Performance improvement when using Descriptive programming when compared to Object Repository usage
31. Ability to Debug libraries loaded during run-time using Execute, ExecuteGlobal and ExecuteFile
32. Ability to register generic functions for any object type. Currently RegisterUserFunc can only be used to register the method for a single object type. So if a new Set method is created then multiple RegisterUserFunc statements need to be written. QTP should provided some way to use a pattern or something to apply the same method to multiple object types
33. Ability to Unlock a locked system from within the code34. Ability to prevent screen locking during the execution
35. Ability to debug error which occurs during terminations of script. Currently any errors that occur during the termination of the script cannot be debugged and launches.
Recovery Scenarios Enhancements:
36. Recovery scenarios (RS) to run in a separate thread. Currently recovery scenarios run in the same thread as QTP. This causes recovery scenarios to be useless in case a Modal dialog blocks QTP
37. Option to stop chaining in recovery scenarios. Currently if RS1 and RS2 both match the trigger criteria then both of the scenarios are executed. There is no way to specify that RS2 should not be executed if RS1 is executed
38. Currently there is no way to enumerate recovery scenarios present in a File
39. Recovery scenarios don’t work when they are associated at run-time
Test Reporting Enhancements:
40. Ability to create reports in different format. Excel, Word, HTML etc…
41. Reporting of errors or failure in different categories and priority. E.g. – Reporting a error with severity, priority and category (Application, Script, Validation, Checkpoint)
42. Exact location of the error in the script. This should include the line of code, error number, error statement
43. Direct ability to send report to a specified list of email addresses when the test end
44. Currently the reports can only be viewed through QTP reporter viewer and cannot be viewed on machines without this tool. Report should be made completely Web compatible so that I can be viewed in any browser in the same way it is displayed in report viewer
45. Ability to view status of current Action. Currently Reporter.RunStatus only provides the status of whole test and not for current action
46. Ability to enumerate the current status from within a Test i.e. Actions executed with details, checkpoints executed with details, recovery scenarios executed with details
Checkpoint Enhancements:
47. Ability to alter properties of all checkpoints during run-time. E.g. Expected bitmap of a bitmap checkpoint, expected values of a Table/DB checkpoint etc
48. Ability to create checkpoints at run-time
49. Ability to load checkpoints from a external file at run-time
50. Ability to enumerate all checkpoints present in current script
Hybrid Test Automation Framework
Hi,
Here we go about Hybrid Test Automation Framework.
Prior to knowing about the Hybrid Test Automation Framework , weshould know about the existing frameworks.
Generally we have,
This Hybrid test automation framework is what most frameworks evolve into over time and multiple projects.
Hybrid Automation Frameworks generally can accommodate any of the below:
Keyword-Driven & Data Driven
Test Script Modularity & Data Driven
Keyword-Driven,Data Driven & Test Library Architecture so on so forth.
Here we go about Hybrid Test Automation Framework.
Prior to knowing about the Hybrid Test Automation Framework , weshould know about the existing frameworks.
Generally we have,
- Data Driven Framework
- Test Script Modularity Framework
- Keyword Driven Framework
- Test Library Architecture Framework
- Hybrid Framework
This Hybrid test automation framework is what most frameworks evolve into over time and multiple projects.
Hybrid Automation Frameworks generally can accommodate any of the below:
Keyword-Driven & Data Driven
Test Script Modularity & Data Driven
Keyword-Driven,Data Driven & Test Library Architecture so on so forth.
Lock your PC automatically after the execution of QTP Scripts
Hi ,
The beauty of Automation Testing is that Scripts are run in an unattended mode.
Thus, what people usually do is, prepare the batch of scripts and leave for their homes. After the batch gets over, no matter even if it passes or even get failed, the PC is unlocked inviting others to view your secret project related data.
This remains a small issue in a simple project based company.
However it can become extremely devastating issue in case of a company having Finance or Banking related projects, having top most concern for the security of its data.
So one wonders as to what can be the way by which this situation can be tackled?
You can use the following QTP Script to lock your PC :
Set obj = CreateObject("WScript.Shell")
sCmnd = "%windir%\SYSTEM32\rundll32.exe user32.dll,LockWorkStation"
obj.Run sCmnd, 0, FalseThe above QTP script will lock your PC automatically.
Moreover, I will suggest you to create this script as a separate script and call this script lastly in your batch. This will solve the purpose :)
The beauty of Automation Testing is that Scripts are run in an unattended mode.
Thus, what people usually do is, prepare the batch of scripts and leave for their homes. After the batch gets over, no matter even if it passes or even get failed, the PC is unlocked inviting others to view your secret project related data.
This remains a small issue in a simple project based company.
However it can become extremely devastating issue in case of a company having Finance or Banking related projects, having top most concern for the security of its data.
So one wonders as to what can be the way by which this situation can be tackled?
You can use the following QTP Script to lock your PC :
Set obj = CreateObject("WScript.Shell")
sCmnd = "%windir%\SYSTEM32\rundll32.exe user32.dll,LockWorkStation"
obj.Run sCmnd, 0, FalseThe above QTP script will lock your PC automatically.
Moreover, I will suggest you to create this script as a separate script and call this script lastly in your batch. This will solve the purpose :)
Function for Excel Cell Colors
Hi All,
Hope all of you are doing well....:)
Here i am providing an Userdefined Function for displaying the cell colors of Excel document.
' Function Defination:
Function ExcelCellColors_display(FilePath)
Dim xl
Set xl=CreateObject("Excel.Application")
xl.visible=True
xl.WorkBooks.Open FilePath
' Retrieving the rowcount used
rc=xl.Activesheet.usedrange.rows.count
' Clearing the existing Data in excel (If any)
For j=1 to rc
xl.Cells(j,1).interior.colorindex=null
xl.Cells(j,1).value=Null
xl.Cells(j,2).value=Null
xl.Cells(j,2).interior.colorindex=null
Next
xl.cells(1,1).value="Color"
xl.cells(1,2).value="Color Index"
' Filling the colors & colorindex values
For i=2 to 56
xl.Cells(i,1).interior.colorindex=i-1
xl.Cells(i,2).value=xl.Cells(i,1).interior.colorindex
Next
xl.ActiveworkBook.Save
xl.ActiveworkBook.Save
wait(1)
xl.Application.quit
Set xl=nothing
End Function
'Function Declaration/Calling:
Call ExcelCellColors_display( "D:\Documents and Settings\Sree\Desktop\Excel_colors.xls")
Output:
Sunday, April 26, 2009
Get Size of Folder/File
Hi All,
Here iam providing a simple way of finding the size of required folder/file.
Try the below code & implement the same wherever & whenever applicable/required.
' Get the size of folder:
dim fso
foldername="Sreekanth"
Set fso = CreateObject( "Scripting.FileSystemObject" )
Set folder1 = fso.GetFolder( "D:\Documents and Settings\Sree\Desktop\"&foldername)
msgbox "Size of Folder "&foldername&" :- "&folder1.Size&" bytes"
Set fso=Nothing
Set fso=Nothing
' Output :
' Get the size of file:
Set fso = CreateObject( "Scripting.FileSystemObject" )
fname="qtpinf"
Set folder1 = fso.Getfile("D:\Documents and Settings\Sree\Desktop\"&fname&".doc")
msgbox "Size of File "&fname&" :- "&folder1.Size&" bytes"
Set fso=Nothing
' Output :
Hi All,
Here i am providing the way of Deleting the Cookies from the browser.
' Way 1:
systemutil.Run "D:\Program Files\Internet Explorer\iexplore.exe"
Dim brw
Set brw=Description.Create()
brw( "micclass" ).Value ="Browser"
brw("CreationTime").Value=0
wait(2)
Browser(brw).WinToolbar("Class Name:=WinToolbar","nativeclass:=ToolbarWindow32","Location:=0").Press "&Tools"
Browser(brw).WinMenu("menuobjtype:=3").Select "Delete Browsing History..."
Browser(brw).Dialog("Class Name:=Dialog","text:=Delete Browsing History").WinButton("Class Name:=WinButton","text:=Delete c&ookies...").Click
Browser(brw).Dialog("Class Name:=Dialog","text:=Delete Browsing History").Dialog("text:=Delete Cookies").WinButton("Class Name:=WinButton","text:=&Yes").Click
Browser(brw).Dialog("Class Name:=Dialog","text:=Delete Browsing History").WinButton("Class Name:=WinButton","text:=&Close").Click
Browser(brw).Close
' Way 2 :
Function ClearCookies()
SystemUtil.Run "Control.exe","inetcpl.cpl"
Set objShell = CreateObject("Wscript.Shell")
Do Until Success = True
Success = objShell.AppActivate("Internet Properties")
Wait(1)
Loop
objShell.Sendkeys "%i"
Wait(1)
objShell.Sendkeys "{ENTER}"
Wait(1)
objShell.Sendkeys "%f"
Wait(1)
objShell.Sendkeys "%d"
Wait(1)
objShell.Sendkeys "{ENTER}"
Wait(4)
objShell.Sendkeys "{ENTER}"
End Function
' Call the above function
Call ClearCookies()
Here i am providing the way of Deleting the Cookies from the browser.
' Way 1:
systemutil.Run "D:\Program Files\Internet Explorer\iexplore.exe"
Dim brw
Set brw=Description.Create()
brw( "micclass" ).Value ="Browser"
brw("CreationTime").Value=0
wait(2)
Browser(brw).WinToolbar("Class Name:=WinToolbar","nativeclass:=ToolbarWindow32","Location:=0").Press "&Tools"
Browser(brw).WinMenu("menuobjtype:=3").Select "Delete Browsing History..."
Browser(brw).Dialog("Class Name:=Dialog","text:=Delete Browsing History").WinButton("Class Name:=WinButton","text:=Delete c&ookies...").Click
Browser(brw).Dialog("Class Name:=Dialog","text:=Delete Browsing History").Dialog("text:=Delete Cookies").WinButton("Class Name:=WinButton","text:=&Yes").Click
Browser(brw).Dialog("Class Name:=Dialog","text:=Delete Browsing History").WinButton("Class Name:=WinButton","text:=&Close").Click
Browser(brw).Close
' Way 2 :
Function ClearCookies()
SystemUtil.Run "Control.exe","inetcpl.cpl"
Set objShell = CreateObject("Wscript.Shell")
Do Until Success = True
Success = objShell.AppActivate("Internet Properties")
Wait(1)
Loop
objShell.Sendkeys "%i"
Wait(1)
objShell.Sendkeys "{ENTER}"
Wait(1)
objShell.Sendkeys "%f"
Wait(1)
objShell.Sendkeys "%d"
Wait(1)
objShell.Sendkeys "{ENTER}"
Wait(4)
objShell.Sendkeys "{ENTER}"
End Function
' Call the above function
Call ClearCookies()
Using the Windows API in QTP
Hi All,
Here i am providing an overview of usage of Windows API in QTP.
Windows API :
Using the Windows API, you can extend testing abilities and add usability and flexibility to your tests and function libraries. The Windows operating system provides a large number of functions to help you control and manage Windows operations. You can use these functions to obtain additional functionality.
The Windows API is documented in the Microsoft MSDN Web site, which can be found at: http://msdn.microsoft.com/library/en-us/winprog/winprog/windows_api_start_page.asp?frame=trueA reference to specific API functions can be found at: http://msdn.microsoft.com/library/en-us/winprog/winprog/windows_api_reference.asp?frame=true
To use Windows API functions:
1. In MSDN, locate the function you want to use in your test or function library.
2. Read its documentation and understand all required parameters and return value(s).
3. Note the location of the API function. API functions are located inside Windows DLLs. The name of the DLL in which the requested function is located is usually identical to the Import Library section in the function's documentation. For example, if the documentation refers to User32.lib, the function is located in a DLL named User32.dll, typically located in your System32 library.
4. Use the QuickTest Extern object to declare an external function. For more information, refer to the QuickTest Professional Object Model Reference.
The following example declares a call to a function called GetForegroundWindow, located in user32.dll:
Extern. Declare micHwnd, "GetForegroundWindow", "user32.dll", "GetForegroundWindow"
5. Call the declared function, passing any required arguments, for example, hwnd = Extern.GetForegroundWindow().
In this example, the foreground window's handle is retrieved. You can enhance your test or function library if the foreground window is not in the object repository or cannot be determined beforehand (for example, a window with a dynamic title). You may want to use this handle as part of a programmatic description of the window, for example:
Window("HWND:="&hWnd).Close
In some cases, you may have to use predefined constant values as function arguments. Since these constants are not defined in the context of your test or function, you need to find their numerical value to pass them to the called function. The numerical values of these constants are usually declared in the function's header file. A reference to header files can also be found in each function's documentation under the Header section. If you have Microsoft Visual Studio installed on your computer, you can typically find header files under X:\Program Files\Microsoft Visual Studio\VC98\Include.
For example, the GetWindow API function expects to receive a numerical value that represents the relationship between the specified window and the window whose handle is to be retrieved. In the MSDN documentation, you can find the constants: GW_CHILD, GW_ENABLEDPOPUP, GW_HWNDFIRST, GW_HWNDLAST, GW_HWNDNEXT, GW_HWNDPREV and GW_HWNDPREV. If you open the WINUSER.H file, mentioned in the GetWindow documentation, you will find the following flag values:
/*
* GetWindow() Constants
*/
#define GW_HWNDFIRST 0
#define GW_HWNDLAST 1
#define GW_HWNDNEXT 2
#define GW_HWNDPREV 3
#define GW_OWNER 4
#define GW_CHILD 5
#define GW_ENABLEDPOPUP 6
#define GW_MAX 6
Example
The following example retrieves a specific menu item's value in the Notepad application.
' Constant Values:
Const MF_BYPOSITION = 1024
'API Functions Declarations
Extern.Declare micHwnd,"GetMenu","user32.dll","GetMenu", micHwnd
Extern.Declare micInteger,"GetMenuItemCount","user32.dll","GetMenuItemCount", micHwnd
Extern.Declare micHwnd,"GetSubMenu","user32.dll","GetSubMenu", micHwnd, micInteger
Extern.Declare micInteger,"GetMenuString","user32.dll","GetMenuString", micHwnd, micInteger, micString+micByRef, micInteger, micInteger
‘Notepad.exe
hwin = Window("Notepad").GetROProperty ("hwnd") ' Get Window's handle
MsgBox hwin
men_hwnd = Extern.GetMenu(hwin)' Get window's main menu's handle
MsgBox men_hwnd
‘Use API Functions
item_cnt = Extern.GetMenuItemCount(men_hwnd)
MsgBox item_cnt
hSubm = Extern.GetSubMenu(men_hwnd,0)
MsgBox hSubm
rc = Extern.GetMenuString(hSubm, 0,value, 64 ,MF_BYPOSITION)
MsgBox value
Here i am providing an overview of usage of Windows API in QTP.
Windows API :
Using the Windows API, you can extend testing abilities and add usability and flexibility to your tests and function libraries. The Windows operating system provides a large number of functions to help you control and manage Windows operations. You can use these functions to obtain additional functionality.
The Windows API is documented in the Microsoft MSDN Web site, which can be found at: http://msdn.microsoft.com/library/en-us/winprog/winprog/windows_api_start_page.asp?frame=trueA reference to specific API functions can be found at: http://msdn.microsoft.com/library/en-us/winprog/winprog/windows_api_reference.asp?frame=true
To use Windows API functions:
1. In MSDN, locate the function you want to use in your test or function library.
2. Read its documentation and understand all required parameters and return value(s).
3. Note the location of the API function. API functions are located inside Windows DLLs. The name of the DLL in which the requested function is located is usually identical to the Import Library section in the function's documentation. For example, if the documentation refers to User32.lib, the function is located in a DLL named User32.dll, typically located in your System32 library.
4. Use the QuickTest Extern object to declare an external function. For more information, refer to the QuickTest Professional Object Model Reference.
The following example declares a call to a function called GetForegroundWindow, located in user32.dll:
Extern. Declare micHwnd, "GetForegroundWindow", "user32.dll", "GetForegroundWindow"
5. Call the declared function, passing any required arguments, for example, hwnd = Extern.GetForegroundWindow().
In this example, the foreground window's handle is retrieved. You can enhance your test or function library if the foreground window is not in the object repository or cannot be determined beforehand (for example, a window with a dynamic title). You may want to use this handle as part of a programmatic description of the window, for example:
Window("HWND:="&hWnd).Close
In some cases, you may have to use predefined constant values as function arguments. Since these constants are not defined in the context of your test or function, you need to find their numerical value to pass them to the called function. The numerical values of these constants are usually declared in the function's header file. A reference to header files can also be found in each function's documentation under the Header section. If you have Microsoft Visual Studio installed on your computer, you can typically find header files under X:\Program Files\Microsoft Visual Studio\VC98\Include.
For example, the GetWindow API function expects to receive a numerical value that represents the relationship between the specified window and the window whose handle is to be retrieved. In the MSDN documentation, you can find the constants: GW_CHILD, GW_ENABLEDPOPUP, GW_HWNDFIRST, GW_HWNDLAST, GW_HWNDNEXT, GW_HWNDPREV and GW_HWNDPREV. If you open the WINUSER.H file, mentioned in the GetWindow documentation, you will find the following flag values:
/*
* GetWindow() Constants
*/
#define GW_HWNDFIRST 0
#define GW_HWNDLAST 1
#define GW_HWNDNEXT 2
#define GW_HWNDPREV 3
#define GW_OWNER 4
#define GW_CHILD 5
#define GW_ENABLEDPOPUP 6
#define GW_MAX 6
Example
The following example retrieves a specific menu item's value in the Notepad application.
' Constant Values:
Const MF_BYPOSITION = 1024
'API Functions Declarations
Extern.Declare micHwnd,"GetMenu","user32.dll","GetMenu", micHwnd
Extern.Declare micInteger,"GetMenuItemCount","user32.dll","GetMenuItemCount", micHwnd
Extern.Declare micHwnd,"GetSubMenu","user32.dll","GetSubMenu", micHwnd, micInteger
Extern.Declare micInteger,"GetMenuString","user32.dll","GetMenuString", micHwnd, micInteger, micString+micByRef, micInteger, micInteger
‘Notepad.exe
hwin = Window("Notepad").GetROProperty ("hwnd") ' Get Window's handle
MsgBox hwin
men_hwnd = Extern.GetMenu(hwin)' Get window's main menu's handle
MsgBox men_hwnd
‘Use API Functions
item_cnt = Extern.GetMenuItemCount(men_hwnd)
MsgBox item_cnt
hSubm = Extern.GetSubMenu(men_hwnd,0)
MsgBox hSubm
rc = Extern.GetMenuString(hSubm, 0,value, 64 ,MF_BYPOSITION)
MsgBox value
Create Log Files in QTP
Hi All ,
Here i am providing the function which creates Log files in QTP.
'===========================================
' Function: WriteLog
' description : Writes a message to a log file. File is created
' inside a Log folder of the current directory or on the Desktop
' Parameters :
'strCode is a code to prefix the message with.
'strMessage is the message of file.
'===========================================
Function WriteLog(strCode, strMessage)
Dim objFS
Dim objFS
Dim objFile
Dim objFolder
Dim strFileName
Set objFS = CreateObject("Scripting.FileSystemObject")
If Not objFS.FolderExists(objFS.GetAbsolutePathName(".") & "\log") Then
Set objFolder = objFS.CreateFolder(objFS.GetAbsolutePathName(".") & "\log")
End If
strFileName = objFS.GetAbsolutePathName(".") & "\log\" & year(date) & month(date) & day(date) & ".log"
Set objFile = objFS.OpenTextFile(strFileName, 8, True)
strFileName = objFS.GetAbsolutePathName(".") & "\log\" & year(date) & month(date) & day(date) & ".log"
Set objFile = objFS.OpenTextFile(strFileName, 8, True)
On Error Resume Next
objFile.Write Date & ", " & Time & ", " & strCode & ", " & strMessage & vbcrlf
' disable the on error statement
' disable the on error statement
On Error GoTo 0
objFile.Close
objFile.Close
Set objFS = Nothing
End Function
'Function Calling :
call WriteLog("Fail","Invalid User Credentials")
call WriteLog("Fail","Invalid User Credentials")
Output will be :
Dictionary Objects in QTP
Hi All ,
Here iam providing an overview on "Dictionary Objects" in QTP.
Using the Dictionary Object :
Usage of Dictionary Objects is an alternative to using environment variables to share values between actions. The Dictionary object enables you to assign values to variables that are accessible from all actions (local and external) called in the test in which the Dictionary object is created.
'In order to have IntelliSense for the Dictionary object, and have it recognized by other actions, it is added to the registry .
Dim WshShell
Set WshShell =CreateObject("WScript.Shell")
WshShell.RegWrite "HKCU\Software\Mercury Interactive\QuickTest Professional\MicTest\ReservedObjects\GlobalDictionary\ProgID", "Scripting.Dictionary","REG_SZ"
Set WshShell = Nothing
' After updating the registry, you must close and reopen QuickTest Professional.
‘Available methods for Dictionary Objects :
1) Exists:
Syntax :
GlobalDictionary.Exists() ' Returns True or False
2) Remove:
Syntax :
GlobalDictionary.Remove() ' Remove a specific key
3) RemoveAll:
Syntax :
GlobalDictionary.RemoveAll ' Removes all keys
4) Add:
Syntax :
GlobalDictionary.Add, ' Create a new key and assigns its value
5) Item:
GlobalDictionary.Item() ' Gets/Sets a key value
Have a nice day folks..........
Here iam providing an overview on "Dictionary Objects" in QTP.
Using the Dictionary Object :
Usage of Dictionary Objects is an alternative to using environment variables to share values between actions. The Dictionary object enables you to assign values to variables that are accessible from all actions (local and external) called in the test in which the Dictionary object is created.
'In order to have IntelliSense for the Dictionary object, and have it recognized by other actions, it is added to the registry .
Dim WshShell
Set WshShell =CreateObject("WScript.Shell")
WshShell.RegWrite "HKCU\Software\Mercury Interactive\QuickTest Professional\MicTest\ReservedObjects\GlobalDictionary\ProgID", "Scripting.Dictionary","REG_SZ"
Set WshShell = Nothing
' After updating the registry, you must close and reopen QuickTest Professional.
‘Available methods for Dictionary Objects :
1) Exists:
Syntax :
GlobalDictionary.Exists(
2) Remove:
Syntax :
GlobalDictionary.Remove(
3) RemoveAll:
Syntax :
GlobalDictionary.RemoveAll ' Removes all keys
4) Add:
Syntax :
GlobalDictionary.Add
5) Item:
GlobalDictionary.Item(
Have a nice day folks..........
Function for Capturing Desktop Screenshot
Hi All,
Here i am providing the user defined function which will captures the screenshot of desktop & stores into required location.
' Function Defination :
Function ScreenShot()
dim strPNG
dim objDesktop
' set a unique file name using the date/time
strPNG = "C:\Screenshot_" &day(Date)&" - "&month(Date)&"-"&year(Date)&"##"& hour(time) &". "& minute(time) &". "& second(time) & ".png"
Set objDesktop=Desktop
' capture a png of the desktop
'captures the screenshot(.png img) into above specified location
objDesktop.CaptureBitmap strPNG,true
' captures the screenshot into current results folders
objDesktop.CaptureBitmap Environment("TestName")&day(Date)&" - "&month(Date)&"-"&year(Date)&".bmp",true
' destroy the object
Set objDesktop = Nothing
End Function
' Function Declaration/Calling
Call ScreenShot()
OutPut :
Screenshot of type .png will be saved in the above Loc given in Variable strPNG.
Screenshot of type .bmp will be saved into current results folders of the script.
Have a nice day.......
Here i am providing the user defined function which will captures the screenshot of desktop & stores into required location.
' Function Defination :
Function ScreenShot()
dim strPNG
dim objDesktop
' set a unique file name using the date/time
strPNG = "C:\Screenshot_" &day(Date)&" - "&month(Date)&"-"&year(Date)&"##"& hour(time) &". "& minute(time) &". "& second(time) & ".png"
Set objDesktop=Desktop
' capture a png of the desktop
'captures the screenshot(.png img) into above specified location
objDesktop.CaptureBitmap strPNG,true
' captures the screenshot into current results folders
objDesktop.CaptureBitmap Environment("TestName")&day(Date)&" - "&month(Date)&"-"&year(Date)&".bmp",true
' destroy the object
Set objDesktop = Nothing
End Function
' Function Declaration/Calling
Call ScreenShot()
OutPut :
Screenshot of type .png will be saved in the above Loc given in Variable strPNG.
Screenshot of type .bmp will be saved into current results folders of the script.
Have a nice day.......
How to Capture ToolTips
Hi All,
Here I am providing fews ways of capturing the Tooltips of objects such as Links,Images,Web Elements So on So forth...
For Example, consider the above page. Here we will capture the Tooltip of the Webelement "Google India" shown in below fig.
' ToolTips for Web Elements:
msgbox browser("Google").Page("Google").WebElement("India").Object.title
OutPut :
In the similar way, check out the below ways of capturing ToolTips for other Object Classes too.
' ToolTips for images :
' ToolTips for images :
msgbox Browser("Yahoo! India").Page("Yahoo! India").Image("Click here").GetROProperty("alt")
' ToolTips for Links :
x=Browser("Yahoo! India").Page("Yahoo! India").Link("All Yahoo! Services").GetROProperty("OuterHtml")
temp=split(x,chr("34"))
ToolTip=temp(1)
msgbox ToolTip
Close All Active Browsers
Hi All,
In this post, I am providing the couple of ways for closing all the active browsers .
Say there are '5' browsers which are opened.
Soultion 1 :
While Browser("CreationTime:=0").Exist
Browser("CreationTime:=0").Close
Wend
Solution 2:
systemutil.CloseProcessByName "iexplore.exe"
Output :
All 5 browsers will be closed......
Have a nice day folks.............
In this post, I am providing the couple of ways for closing all the active browsers .
Say there are '5' browsers which are opened.
Soultion 1 :
While Browser("CreationTime:=0").Exist
Browser("CreationTime:=0").Close
Wend
Solution 2:
systemutil.CloseProcessByName "iexplore.exe"
Output :
All 5 browsers will be closed......
Have a nice day folks.............
Get number of Files in a Folder
Hi All,
Use the following way for finding the number of files in a folder.
Code:
Set objFileSysOb = CreateObject("Scripting.FileSystemObject")
Set colFolderName = objFileSysOb.GetFolder("give entire folder path here")
Set vFiles =colFolderName.Files
Sno=0
For each i in vFiles
d=Split(i,"\")
FileName=d(ubound(d))
Sno=Sno+1
msgbox "File "&Sno&" : "&FileName
Next
msgbox "Number of files in Current Folder : "&vFiles.count
Output :
Use the following way for finding the number of files in a folder.
Code:
Set objFileSysOb = CreateObject("Scripting.FileSystemObject")
Set colFolderName = objFileSysOb.GetFolder("give entire folder path here")
Set vFiles =colFolderName.Files
Sno=0
For each i in vFiles
d=Split(i,"\")
FileName=d(ubound(d))
Sno=Sno+1
msgbox "File "&Sno&" : "&FileName
Next
msgbox "Number of files in Current Folder : "&vFiles.count
Output :
Find the Links Count in a Web Page
Hi All,
'*********************************************
Here i am posting a User defined
function for finding number of objects of required object Type/Class in a
Google Web Page (i.e Link,Image,Web button,Web Edit...So on So forth)
'*********************************************
' Function Defination :
'*********************************************
Function objects_count_in_Page(Req_obj)
Dim obj
Set obj=Description.Create
obj("micclass").Value=Req_obj
Set x=Browser("Google").Page("Google").ChildObjects(obj)
Req_obj_count= x.count()
msgbox Req_obj&"s"&" in WebPage : "&Req_obj_count
End Function
'*********************************************
Function Declarations/Function Calls of above Function:
'*********************************************
Call objects_count_in_Page("Link")
Call objects_count_in_Page("WebButton") :
Call objects_count_in_Page("WebEdit")
Output will be :
No comments:
Post a Comment