当前位置:首页 >> 计算机软件及应用 >>

A Practical Automation Framework


I have been on test automation for years, and I have used many automation test tool, I know the pros and cons of test automation. In my post-graduation student thesis, I used automation as my topic and when I review my thesis, I felt shame about it. Automation is introduced to increase re-usability, liability while reduce human efforts. The test automation framework is a framework to test GUI (Graphic User Interface) and function. The SUT (System under Test) is a C/S program and we used Rational Robot to implement the test cases and test framework. The SUT has 76 windows and over 800 test cases. The whole framework goes like this:

Let me have a brief introduction: Product A is the SUT and Product B is sometimes integrated with Product A to complete some functions for Product A. The first layer is lowest layer and consist of Common Function and .property or .xml from Product a, Product Specific List View Utilities and Product Related Properties File are connect with SUT product A and are developed by developers from Product A. The second layer is middle layer and is separated into 76 files. Each window will have a separated file. In each file, every single checkbox or an edit box or a radio button would be encapsulated as one single independent function, which, we call it a task. Task sometimes will call common functions in first layer to read value from Property file or do other function from first layer. Generally speaking, a task is not closely related to SUT. There is other kind of functions in each of the 76 files called wizards. A wizard calls batches of tasks and complete a series of actions based on user intentions. It is closely connected with SUT. Here is an example on how to distinguish tasks and wizards:

I will take Tencent QQ login window as an example:

Click user name, input user name, clear user name, click user password, input user password, clear user password, check remember password, uncheck remember password, check auto login, uncheck auto login, click login button. These are all valid simple tasks. As for complex wizard, here is only 1: 1 input user name; 2 input user password; 3 click login button. These 3 tasks together make a wizard, which implement the login steps and it is product (business) related. Wizard don`t contains verification point, which should only be included in test cases. The third layer is the test cases layer. It calls verification functions in common functions and wizards. A test case is not allowed to called tasks directly. We have Pros and cons after use 3-tier layer. Pros : 1 1 Isolation to test cases. The test cases don`t need to be updated, you only need to adjust tasks and wizards. Think about the numbers, test cases over 800 but tasks and wizards are in 76 files. Each window has only 1 file. 2 2 Good naming conversions make the test cases easily understood and good to maintain. Everyone can write test cases and only sophisticated can debug and upload good automated test cases. 3 When SUT change slightly, you only need to adjust tasks, you don`t even change wizards or test cases. 4 For localization tests, all you need to change is the .properties file. Cons: 1. It is obviously that the SUT cannot have much GUI change. If the GUI is configurable, you will have to fix on a certain configuration. And test 2 or more different configurations, will increase the flexibility. 2. Common function and wizards will take a long time to complete and be tested. 3. People who don`t familiar with Common Function will take a long time to debug and fix issues. Here are some examples: 1 Properties files

1. STRINGTABLE DISCARDABLE 2. BEGIN 3. 4. 5. 6. 7. 8. END 2 Examples for tasks 1. ' Tasks: 2. 3. ' [All] 4. Declare Sub APSrch_SelectView (ViewName as String) 5. Declare Sub APSrch_ClickClearALL 6. Declare Sub APSrch_ClickSave 7. Declare Sub APSrch_ClickLoad 8. Declare Sub APSrch_ClickSearch 9. Declare Sub APSrch_ClickDone basiclib "A_PowerSearch" () basiclib "A_PowerSearch" () basiclib "A_PowerSearch" () basiclib "A_PowerSearch" () basiclib "A_PowerSearch" () basiclib "A_PowerSearch" IDS_DIALOGS_TITLE_MessageDlg IDS_DIALOGS_TITLE_WarningDlg IDS_DIALOGS_TITLE_ErrorDlg IDS_DIALOGS_TITLE_DirPickerDlg "Message" "Warning" "Error" "Select a Folder:"

IDS_DIALOGS_TITLE_SelectDocuments "Select Documents"

1. '########################################################################## ## 2. '# Sub APSrch_SelectView((ViewName as String)

3. '# DESCRIPTION: 4. '# [Task] Select view in power search.

5. '# EXAMPLES: 6. '# Call APSrch_SelectView("General")

7. '# Orig Author: XX 8. '# Orig Date: April 6, 2006

9. '# History:

10. '#

April 5, 2006

Original Release

11. '########################################################################## ## 12. Sub APSrch_SelectView(ViewName as String) 13. 14. 15. Dim cmbName As String cmbName=A_GetKeyRC("IDS_DESKTOP_LABEL_SelectView") Call A_CmbSelect(cmbName, ViewName)

16. End Sub 3 Example for wizards 1. ' Wizards: 2. 3. Declare Sub APSrch_SearchByProperty basiclib "A_PowerSearch"

(Property as String, Filter as String, Value as String) 4. Declare Sub APSrch_SerachByDocContent (words() as String, condition() as String) 5. Declare Sub APSrch_SearchByDate basiclib "A_PowerSearch" basiclib "A_PowerSearch"

(Property as String, Filter as String, DYear as String, Aonth as String, DDay as String) 1. '########################################################################## ## 2. '# Sub APSrch_SearchByProperty(Property as String,Filter as String,Value

as String) 3. '# DESCRIPTION: 4. '# Search by a property in general tab

5. '# PARAMETERS: 6. '# 7. '# 8. '# [In] [In] [In] Property e.g., "DocumentName" Filter Value e.g., "Contain" e.g., "Test"

9. '# ERRORS:

10. '#

(none)

11. '# EXAMPLES: 12. '# 13. '# Call APSrch_SearchByProperty("DocumentName","Contain","Test") APSrch_SearchByProperty"DocumentName","Contain","Test"

14. '# Orig Author: XX 15. '# Orig Date: May 25, 2005

16. '# History: 17. '# 18. '# May 25, 2005 Original Release

April 11, 2006 XX Modified "APSrch_General_ClickAdd" instead of

"APSrch_ClickAdd" and 19. '# "APSrch_InputValue" 20. '########################################################################## ## 21. Sub APSrch_SearchByProperty(Property as String,Filter as String,Value as String) 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. Call A_Delay(10000) Call APSrch_General_ClickAdd() APSrch_ClickSearch A_Focus A_GetKeyRC("IDD_POWERSEARCH_TEMPLATE.CAPTION") APSrch_SelectProperty Property APSrch_SelectFilter Filter APSrch_General_InputValue Value A_Focus A_GetKeyRC("CPN_DESKTOP") Call ADesk_ClickTopPowerSearch() "APSrch_General_InputValue" instead of

34. End Sub

4 Example for test cases 1. '########################################################################## ## 2. '# Test if we can create a document and later search out 3. '# DESCRIPTION: 4. '# 5. '# 6. 7. '# 8. '########################################################################## ## 9. Sub Test_Search_By_Properties(Property as String,Filter as String,Value as String) 10. 11. Call User_Login(NormalUser1, Password1) 12. Call A_CreateDoc(TestPath1, DocName) 13. Call A_Desktop_Focus() 14. Call A_Desk_ClickTopPowerSearch() 15. 16. Call A_PowerSearch_Focus() 17. Call APSrch_SelectProperty Property 18. Call APSrch_SelectFilter Filter 19. Call APSrch_General_InputValue Value 20. 21. Call APSrch_General_ClickAdd() 22. Call APSrch_ClickSearch() 23. 24. Call A_Delay(10000) 25. 26. Dim Count As Interger

27. Call Count = CommonUtil_GetListView_Count() 28. If Count = 1 then 29. eStamp) 30. Else 31. eStamp) 32. End If 33. 34. Call A_DeleteFileAll() 35. 36. Call A_Logout() 37. End Sub Test_Log("Test_Search_By_Properties","Fail",CommonUtil_GetCurrenTim Test_Log("Test_Search_By_Properties","Pass",CommonUtil_GetCurrenTim

As you can see, the test cases are human readable and the cost for maintain is minimum. Anyone who has coding experience can get familiar with the framework through write 1-2 test cases and debug several times. Here are some advanced topics in the framework: Sometimes, you will have to use derived function for other usage. We all know the common focus function which focus on a windows but what about we will wait for a window to disappear? 1. '########################################################################## ## 2. '# Function A_Focus(strCaption as String) as Integer

3. '# DESCRIPTION: 4. '# Focus object

5. '# PARAMETERS: 6. '# [In] strCaption e.g.,"CPN_DESKTOP"

7. '# RETURNS: 8. '# 9. '# true success false fail

10. '# ERRORS:

11. '#

(none)

12. '# EXAMPLES: 13. '# return = A_Focus("CPN_DESKTOP")

14. '# Orig Author: XX) 15. '# Orig Date: May 09, 2005

16. '# History: 17. '# 18. '# May 09, 2005 Apr 17, 2006 Original Release XX If the window state is minimized, then

restore the position. 19. '########################################################################## ## 20. Function A_Focus(strCaption as String) as Integer 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. result = SQAGetProperty("\;type=window;Caption=" &strCaption, "WindowState", state) 31. 32. 33. 34. 35. 36. ' Valid WindowState: ' 0 : Normal ' 1 : Minimized ' 2 : Maximized If (state = "1") Then Window SetContext, "Caption=" &strCaption , "" Dim Result as Integer Result=SQAWaitForObject("\;type=window;Caption=" &strCaption, 20000) If Result<>sqaSuccess Then A_Focus= false Exit Function Else ' If the window state is minimized, then restore it. Dim state As String

37. 38. 39. 40. 41. 42.

Window RestorePos, "", "" End If

A_Focus= true Window SetContext, "Caption=" &strCaption , "" End If

43. End Function 1. '########################################################################## ## 2. '# Function A_WaitWindowAppear(caption As String, Optional Timeout As As Integer

Variant)

3. '# DESCRIPTION: 4. '# Wait for the object to appear

5. '# PARAMETERS: 6. '# 7. '# 8. '# 9. '# EXAMPLES: 10. '# result = A_WaitWindowAppear("Type=CheckBox;WindowIndex=19") [In] [In] caption Timeout caption title time out

11. '# Orig Author: XX 12. '# Orig Date: Apr 05, 2006

13. '# History: 14. '# June 08, 2005 Original Release

15. '########################################################################## ## 16. Function A_WaitWindowAppear(caption As String,Optional Timeout As Variant) As Integer 17.

18.

If A_WaitForObject("\;Type=window;Caption=" &caption,Timeout) = sqaSuccess Then

19. 20. 21. 22. 23. 24. Else

A_WaitWindowAppear = True Window SetContext, "Caption=" &caption , "" Exit Function

A_WaitWindowAppear = false SQALogMessagesqaWarning, "Caption [" & caption & "] has not appeared" , ""

25. 26.

End If

27. End Function 1. '########################################################################## ## 2. '# Function A_WaitWindowDisappear(recMethod As String, Optional Timeout As As Integer

Variant)

3. '# DESCRIPTION: 4. '# 5. '# 6. '# EXAMPLES: 7. '# result = A_WaitWindowDisappear("Type=CheckBox;WindowIndex=19") Wait for the Window to disappear

8. '# Orig Author: XX 9. '# Orig Date: June 08, 2005

10. '# History: 11. '# June 08, 2005 Original Release

12. '########################################################################## ## 13. Function A_WaitWindowDisappear(recMethod As String, Optional Timeout As Variant) As Integer

14.

A_WaitWindowDisappear = A_WaitObjectDisappear("\;type=window;Caption=" &recMethod, Timeout)

15. End Function As you can see, we will implement many other functions for other usages. The Second problem is that there will be repeat or Polymorphism in the functions. Sometimes you will have to look inside the code to know what 2 wizards are different, especially when there are optional parameters. Here is an example, we will import a document but the add document window can has different parameters, some are mandatory and some are optional.

1. Declare Function ADoc_AddPolicy String, FileName As String, _ 1. Declare Function ADoc_AddPolicy1 String, _ 2. String, _ 3. ExpireDate As Variant, _ 4. Country As Variant, _ 5. City As Variant, _ 6. Desc As Variant, _ 7. StateName As Variant, _ 8. Template As Variant, _ 9. TstTimeStamp As Variant, _ 10. TstTime As Variant) As Integer

basiclib "A_Document" (Title As

basiclib "A_Document" (Title As

FileName As

Optional

Optional

Optional

Optional

Optional

Optional

Optional

Optional

The first function only input required fields while the second can specify optional fields. The last thing to talk about is the name conversion for each part in a single test case. In order to isolate each test case, make failure of one test case will not block another. We have below agreements: 1 Part is to make environment. Say, in order to search a document, I will import/create one first. 2 Verify the search function and search out the document in part 1. 3 Delete the document in part 1. We have below 2 name methods

1:PreEnv_CreateDoc Verify_SearchDoc PostEnv_DeleteDoc 2:Part1 Part2 Part3 I assume you choose the first 1 without hesitate. ? Think about it in a more practical way. What if your part 1 has to finish 10 complex steps? We see all kinds of name from test cases, people who debug the code even want to suicide himself. So we choose the second type. Anyway, stability and simplicity overcomes human readable. Last thing not the least thing is that you have to pay attention for your algorithm. Once they wrote a function to get a value from an excel like table, say, get row 3 column 4 from a 10X10 table. That single function runs for 15 seconds, they used a bad algorithm. After improvident, you only need 4 seconds for that.

Automation is not a silver ballet for bugs. You will pay more with less in the beginning and it is strongly advised only used in regression tests. Write test framework and test cases are 2 sides of a coin and better has someone who works on both sides. People who design framework can know the business and people who wrote test cases can know the framework better as well.


相关文章:
更多相关标签: