VS2010 測試功能之旅:編碼的UI測試(4)-通過編寫測試代碼的方式建立UI測試(下)
回顧
最近比較忙,距離上次更新的時間較久,見諒。
在本章上部分,介紹了“添加用戶”窗口的測試代碼編寫。想必大家也看到了,在UIMap.cs文件中實現自定義編碼是一件很輕松的事情,接下來將介紹下個部分,查詢用戶窗體的測試代碼的編寫,以及他們測試的關聯。
示例程序介紹
系統主窗口:(下載點我)
該系統擁有兩個功能,“添加用戶”和“查詢用戶”:
點擊添加用戶后,進入添加用戶子窗體:(“添加用戶”窗口的測試代碼編寫在上部分已經實現)
如果在之前的主窗口,點擊查詢用戶,則進入查詢用戶子窗體:
注:系統默認自帶了5個用戶TestUser1, TestUser2, TestUser3, TestUser4, TestUser5。
這個窗體不會彈任何提示框,默認進入窗體時,DataGridView里面沒有加載數據,現在進行一個說明:
查詢條件-用戶名:表示是否按用戶名查詢(非模糊查詢),如果不輸入,默認為不按其查詢。
查詢條件-用戶類型:有三個選項“所有”,“管理員”,“一般用戶”。
查詢條件-日期:表示是否按日期查詢,如果勾上了日期CheckBox,則旁邊的DateTimePicker會啟用,然后選擇一個具體的日期。
按鈕-查詢:就會按以上條件查詢。
按鈕-重置:用戶名清空,用戶類型變成所有,日期取消勾選。
文本框-用戶備注:當查詢出數據以后,每選擇DataGridView里面中的一行數據,用戶備注TextBox會自動加載當前行的用戶備注。
如何設計測試
現在需要明確的就是,我們既需要檢查“查詢用戶”窗口的基本功能,又需要確定之前在“添加用戶”窗口添加的用戶是否被添加了進來,所以這里的檢查尤其重要,根據剛才的功能描述,現在需要編寫測試設計。(在看下面的設計之前大家可以先試著自己設計下) 。
自動化測試,關鍵不在技術,而是在測試設計上,所以這里需要設計得比較全面:
步驟序號 |
操作步驟 |
檢查點 |
1 |
在主窗口菜單點擊用戶查詢 |
檢測查詢用戶子窗口是否彈出 |
2 |
用戶名為空,用戶類型為“所有”,不勾選時間,點擊查詢,記錄查詢出的用戶行數,程序默認選中第一行,這時我們選中第二行 |
檢測“用戶備注”一列的值是否和下方的“用戶備注”文本框的值一致 |
3 |
加的用戶,其他條件不變,點擊查詢(例如,在上個部分的示例中,我們使用的是”TestUser6”) |
查詢出用戶名為TestUser6的一條數據 |
4 |
用戶名為一個不存在的用戶“testuser100”,其他條件不變,點擊查詢 |
未查詢出數據 |
5 |
將用戶名設置為空,其他條件不變,用戶類型為“管理員”,記錄查詢出的行數 |
查詢出所有為“管理員”的用戶(注,為了方便,這里沒有使用從數據庫比對,而只使用查詢條件與查詢出的數據比對,實際項目中可能使用數據庫比對) |
6 |
將用戶類型設置為“一般用戶”,其他條件不變,記錄查詢出的行數 |
查詢出所有為“一般用戶”的用戶 |
7 |
使用剛才用戶類型分別為“所有”,“管理員”,“一般用戶”查詢出的數據行數,進行比對 |
一般用戶行數+管理員用戶行數=所有用戶行數 |
8 |
用戶名為空,用戶類型為“所有”,勾選時間,并進行選擇“2008-1-11” |
查詢出所有添加時間為“2008-1-11”的用戶 |
9 |
將條件設置為剛才我們在添加用戶窗口添加的用戶信息(使用我們在上一個示例中使用的值,如”TestUser6”,”一般用戶”,時間為添加時間,時間這個需要用到某個變量來記錄) |
查詢出對應的一條數據 |
10 |
點擊重置按鈕 |
用戶名為空,用戶類型為“所有”,不勾選時間 |
11 |
點擊退出 |
退出窗口 |
接下來將以上的檢查點轉換為代碼。
對測試進行編碼
我們可以接著上次錄制的代碼來編寫,因為在上個部分對于某些編寫方式(例如先捕獲對象再編寫和先錄制再轉移修改的方式)已經描述得很詳細了,下面默認使用這些方式,因此就不一一闡述對象的捕捉過程了。這里只介紹上個部分沒有介紹的注意點和和給出主要代碼。
由于是接著上個部分的代碼寫,這里需要注釋掉AddUserUIMap.cs中Step7_CloseWindows的兩句代碼,以免他在測試結束后將主窗口關閉掉:
{
//操作步驟
bool isClosed;
Mouse.Click(this.UI添加用戶Window.UI取消Window.UI取消Button, new Point(1, 1));
//和WaitForControlExist相反,這里是最長等待他3秒關閉,如果3秒內關閉返回true,否則為false
isClosed= this.UI添加用戶Window.WaitForControlNotExist(3000);
// 這里添上了注釋,以免將主窗口關閉掉
// Mouse.Click(this.UI系統主窗口Window.UI系統主窗口TitleBar.UICloseButton, new Point(1, 1));
// isClosed &= this.UI系統主窗口Window.WaitForControlNotExist(3000);
//檢查點
Assert.IsTrue(isClosed, "點擊退出,檢測是否退出添加用戶子窗體和主窗體失敗");
}
接下來,我們通過在項目中添加新項的方式新建一個SearchUserUIMap.uitest,在這個UIMap的.cs中來編寫我們對于“查詢用戶”這個窗口的操作。
實現步驟1
步驟序號 |
操作步驟 |
檢查點 |
1 |
在主窗口菜單點擊用戶查詢 |
檢測查詢用戶子窗口是否彈出 |
相信這個很簡單,兩下就可以通過錄制然后修改的方式編寫出來:
{
WinMenuItem uI查詢用戶MenuItem = this.UI系統主窗口Window.UIMenuStrip1MenuBar.UI用戶管理MenuItem.UI查詢用戶MenuItem;
//操作步驟:Click '用戶管理' -> '查詢用戶' menu item
Mouse.Click(uI查詢用戶MenuItem, new Point(1, 1));
//檢查點:檢查查詢用戶子窗口是否彈出
Assert.IsTrue(this.UI查詢用戶Window.WaitForControlExist(6000), "點擊查詢用戶,檢測查詢用戶子窗口彈出失敗");
}
實現步驟2
步驟序號 |
操作步驟 |
檢查點 |
2 |
用戶名為空,用戶類型為“所有”,不勾選時間,點擊查詢,記錄查詢出的用戶行數,程序默認選中第一行,這時我們選中第二行 |
檢測“用戶備注”一列的值是否和下方的“用戶備注”文本框的值一致 |
這一步需要注意的就是,首先這里有一個選行的操作,然后需要從表里單元格當中取值,最后與文本框的值進行比對,這里之所以需要記錄這個RowCount,是因為在步驟7的時候會用于比對,這里需要用準星首先捕獲到這個GridViewTable,然后將其添加到對象庫:
然后才開始錄制并編寫代碼,如下:
public void Step2_SearchWithOutCondition()
{
WinButton uI查詢Button = this.UI查詢用戶Window.UI查詢Window.UI查詢Button;
//操作步驟
Mouse.Click(uI查詢Button, new Point(1, 1));//Click '查詢' button
System.Threading.Thread.Sleep(3000);//等待3秒,應付可能出現的查詢延時
AllUser = this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows.Count;//獲取行數
WinRow row2 = this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows[1] as WinRow;
Mouse.Click(row2.Cells[0], new Point(10, 10));//點擊第二行第一個單元格,用以將第二行其選中
System.Threading.Thread.Sleep(1000);//等待1秒,應付可能出現的查詢延時
//檢查點:檢測“用戶備注”一列的值是否和下方的“用戶備注”文本框的值一致
Assert.AreEqual(this.UI 查詢用戶Window.UITbx_MemoWindow.UITbx_MemoEdit.Text, ((WinCell)row2.Cells[4]).Value,"檢測“用戶備注”一列的值是否和下方的“用戶備注”文本框的值一致失敗");
}
實現步驟3
步驟序號 |
操作步驟 |
檢查點 |
3 |
用戶名為剛才我們在添加用戶窗口添加的用戶,其他條件不變,點擊查詢(例如,在上個部分的示例中,我們使用的是”TestUser6”) |
查詢出用戶名為TestUser6的一條數據 |
步驟3和步驟4是對用戶名這個維度來進行測試,需要和上一個模塊對接,因為在上一個模塊添加了一個用戶,所以這里需要檢查是否能夠查詢出來,需要確定的就是RowCount=1并且第一行第一列數據為”TestUser6”才算正確,代碼如下:
{
string NewUser = "TestUser6";
WinEdit uITbx_UserNameEdit = this.UI查詢用戶Window.UITbx_UserNameWindow.UITbx_UserNameEdit;
WinButton uI查詢Button = this.UI查詢用戶Window.UI查詢Window.UI查詢Button;
//操作步驟
uITbx_UserNameEdit.Text = NewUser;
Mouse.Click(uI查詢Button, new Point(1, 1));//Click '查詢' button
System.Threading.Thread.Sleep(3000);//等待3秒,應付可能出現的查詢延時
//檢查點:查詢出用戶名為TestUser6的一條數據
bool isValid = 1==this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows.Count;
WinCell cell = ((WinRow)UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows[0]).Cells[1] as WinCell;
isValid &= cell.Value == NewUser;
Assert.IsTrue(isValid, "查詢出用戶名為"+NewUser+"的一條數據失敗");
}
實現步驟4
步驟序號 |
操作步驟 |
檢查點 |
4 |
用戶名為一個不存在的用戶“testuser100”,其他條件不變,點擊查詢 |
未查詢出數據 |
這是一個反例的測試,很明顯只要RowCount為0就可以通過測試:
{
string ErrorUser="TestUser1000";
WinEdit uITbx_UserNameEdit = this.UI查詢用戶Window.UITbx_UserNameWindow.UITbx_UserNameEdit;
WinButton uI查詢Button = this.UI查詢用戶Window.UI查詢Window.UI查詢Button;
//操作步驟
uITbx_UserNameEdit.Text = ErrorUser;
Mouse.Click(uI查詢Button, new Point(1, 1));//Click '查詢' button
System.Threading.Thread.Sleep(3000);//等待3秒,應付可能出現的查詢延時
//檢查點:未查詢出數據
Assert.IsTrue(0 == this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows.Count, "未查詢出數據失敗");
}
實現步驟5
步驟序號 |
操作步驟 |
檢查點 |
5 |
將用戶名設置為空,其他條件不變,用戶類型為“管理員”,記錄查詢出的行數 |
查詢出所有為“管理員”的用戶(注,為了方便,這里沒有使用從數據庫比對,而只使用查詢條件與查詢出的數據比對,實際項目中可能使用數據庫比對) |
步驟5,6,7是對用戶類型這個維度來進行測試,在步驟5中,我們需要遍歷每一行中的“用戶類型”列,判斷他是不是等于“管理員”,并記錄一共查詢出多少條數據:
public void Step5_SearchWithAdminOnly()
{
string UserType = "管理員";
WinEdit uITbx_UserNameEdit = this.UI查詢用戶Window.UITbx_UserNameWindow.UITbx_UserNameEdit;
WinComboBox uI用戶類型ComboBox = this.UI查詢用戶Window.UICbx_UserTypeWindow.UI用戶類型ComboBox;
WinButton uI查詢Button = this.UI查詢用戶Window.UI查詢Window.UI查詢Button;
//操作步驟
uITbx_UserNameEdit.Text = "";
uI用戶類型ComboBox.SelectedItem = UserType;
Mouse.Click(uI查詢Button, new Point(1, 1));//Click '查詢' button
System.Threading.Thread.Sleep(3000);//等待3秒,應付可能出現的查詢延時
AdminUser = this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows.Count;//獲取行數
//檢查點:查詢出所有為“管理員”的用戶
bool isValid = true;
foreach (WinRow winrow in this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows)
{
isValid &= ((winrow.Cells[2] as WinCell).Value == UserType);
}
Assert.IsTrue(isValid, "查詢出所有為“管理員”的用戶失敗");
}
實現步驟6
步驟序號 |
操作步驟 |
檢查點 |
6 |
將用戶類型設置為“一般用戶”,其他條件不變,記錄查詢出的行數 |
查詢出所有為“一般用戶”的用戶 |
和步驟5是一樣的,需要遍歷每一行中的“用戶類型”列,判斷他是不是等于“一般用戶”,并記錄一共查詢出多少條數據:
public void Step6_SearchWithNormalUserOnly()
{
string UserType = "一般用戶";
WinEdit uITbx_UserNameEdit = this.UI查詢用戶Window.UITbx_UserNameWindow.UITbx_UserNameEdit;
WinComboBox uI用戶類型ComboBox = this.UI查詢用戶Window.UICbx_UserTypeWindow.UI用戶類型ComboBox;
WinButton uI查詢Button = this.UI查詢用戶Window.UI查詢Window.UI查詢Button;
//操作步驟
uITbx_UserNameEdit.Text = "";
uI用戶類型ComboBox.SelectedItem = UserType;
Mouse.Click(uI查詢Button, new Point(1, 1));//Click '查詢' button
System.Threading.Thread.Sleep(3000);//等待3秒,應付可能出現的查詢延時
NormalUser = this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows.Count;//獲取行數
//檢查點:查詢出所有為“一般用戶”的用戶
bool isValid = true;
foreach (WinRow winrow in this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows)
{
isValid &= ((winrow.Cells[2] as WinCell).Value == UserType);
}
Assert.IsTrue(isValid, "查詢出所有為“一般用戶”的用戶失敗");
}
實現步驟7
步驟序號 |
操作步驟 |
檢查點 |
7 |
使用剛才用戶類型分別為“所有”,“管理員”,“一般用戶”查詢出的數據行數,進行比對 |
一般用戶行數+管理員用戶行數=所有用戶行數 |
現在應該了解之所以需要記錄下不同用戶類型記錄數的原因了吧?代碼如下:
{
Assert.AreEqual(AdminUser + NormalUser, AllUser, "檢查'一般用戶行數+管理員用戶行數=所有用戶行數'失敗");
}
實現步驟8
步驟序號 |
操作步驟 |
檢查點 |
8 |
用戶名為空,用戶類型為“所有”,勾選時間,并進行選擇“2008-1-11” |
查詢出所有添加時間為“2008-1-11”的用戶 |
步驟8是對時間維度進行一個測試,現在如果我們選擇了2008-1-11,那么只需要遍歷查詢出的各行的“時間”一列是不是為2008-1-11:
{
string DateTimeAsString = "2008-1-11";
WinEdit uITbx_UserNameEdit = this.UI查詢用戶Window.UITbx_UserNameWindow.UITbx_UserNameEdit;
WinComboBox uI用戶類型ComboBox = this.UI查詢用戶Window.UICbx_UserTypeWindow.UI用戶類型ComboBox;
WinCheckBox uI日期CheckBox = this.UI查詢用戶Window.UI日期Window.UI日期CheckBox;
WinDateTimePicker uIDtp_AddTimeDateTimePicker = this.UI 查詢用戶Window.UIDtp_AddTimeWindow.UIDtp_AddTimeDateTimePicker;
WinButton uI查詢Button = this.UI查詢用戶Window.UI查詢Window.UI查詢Button;
//操作步驟
uITbx_UserNameEdit.Text = "";
uI用戶類型ComboBox.SelectedItem = "所有";
uI日期CheckBox.Checked = true;
uIDtp_AddTimeDateTimePicker.DateTimeAsString =DateTimeAsString;
Mouse.Click(uI查詢Button, new Point(1, 1));//Click '查詢' button
System.Threading.Thread.Sleep(3000);//等待3秒,應付可能出現的查詢延時
//檢查點:查詢出所有為“2008-1-11”的用戶
bool isValid = true;
foreach (WinRow winrow in this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows)
{
string[] DateNumbers = DateTimeAsString.Split('-');
DateTime dt= Convert.ToDateTime((winrow.Cells[3] as WinCell).Value);
isValid &= Convert.ToInt32(DateNumbers[0]) == dt.Year;
isValid &= Convert.ToInt32(DateNumbers[1]) == dt.Month;
isValid &= Convert.ToInt32(DateNumbers[2]) == dt.Day;
}
Assert.IsTrue(isValid, "查詢出所有為“2008-1-11”的用戶失敗");
}
實現步驟9
步驟序號 |
操作步驟 |
檢查點 |
9 |
將條件設置為剛才我們在添加用戶窗口添加的用戶信息(使用我們在上一個示例中使用的值,如”TestUser6”,”一般用戶”,時間為添加時間,時間這個需要用到某個變量來記錄) |
查詢出對應的一條數據 |
步驟9是進行一次復合條件查詢的測試,這次測試就用到之前我們在添加用戶的時候的數據,需要注意的是,因為添加時間是不確定的,所以我們需要修改之前錄制的代碼,將他的值賦給一個變量,需要修改的AddUserUiMap.cs中的方法Step6_AddUserSuccess,讓其有一個返回值返回當前時間,代碼如下:
{
//操作步驟
this.UI添加用戶Window.UITbx_UserNameWindow.UITbx_UserNameEdit.Text = "TestUser6";
this.UI添加用戶Window.UICbx_UserTypeWindow.UI用戶類別ComboBox.SelectedItem = "一般用戶";
this.UI添加用戶Window.UITbx_MemoWindow.UITbx_MemoEdit.Text = "Test";
Mouse.Click(this.UI添加用戶Window.UI添加Window.UI添加Button, new Point(1, 1));
//檢查點:首先檢查3秒內是否有彈出框彈出,如果有,則檢查文本是否是"添加成功!"
this.mUI彈出框Window = new UI彈出框Window();
bool isPopUp = this.UI彈出框Window.UI彈出框Text.WaitForControlExist(3000);
Assert.IsTrue(isPopUp&&this.UI彈出框Window.UI彈出框Text.DisplayText == "添加成功!", "輸入正確,檢測彈出“添加成功!”失敗");
Mouse.Click(this.UIOKWindow.UIOKButton, new Point(1, 1));
//這里是新添加的代碼
return DateTime.Now;
}
然后現在在這里引用之前的變量,來進行操作,代碼如下:
{
string UserName = "TestUser6";
string UserType = "一般用戶";
string AddTime = addTime.Year + "-" + addTime.Month + "-" + addTime.Day;
WinEdit uITbx_UserNameEdit = this.UI查詢用戶Window.UITbx_UserNameWindow.UITbx_UserNameEdit;
WinComboBox uI用戶類型ComboBox = this.UI查詢用戶Window.UICbx_UserTypeWindow.UI用戶類型ComboBox;
WinCheckBox uI日期CheckBox = this.UI查詢用戶Window.UI日期Window.UI日期CheckBox;
WinDateTimePicker uIDtp_AddTimeDateTimePicker = this.UI 查詢用戶Window.UIDtp_AddTimeWindow.UIDtp_AddTimeDateTimePicker;
WinButton uI查詢Button = this.UI查詢用戶Window.UI查詢Window.UI查詢Button;
//操作步驟
uITbx_UserNameEdit.Text = UserName;
uI用戶類型ComboBox.SelectedItem = UserType;
uI日期CheckBox.Checked = true;
uIDtp_AddTimeDateTimePicker.DateTimeAsString = AddTime;
Mouse.Click(uI查詢Button, new Point(1, 1));//Click '查詢' button
System.Threading.Thread.Sleep(3000);//等待3秒,應付可能出現的查詢延時
//檢查點:查詢出用戶名為TestUser6的一條數據
bool isValid = 1 == this.UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows.Count;
WinCell cell = ((WinRow)UI查詢用戶Window.UIUserGridViewWindow.UIDataGridViewTable.Rows[0]).Cells[1] as WinCell;
isValid &= cell.Value == UserName;
Assert.IsTrue(isValid, "查詢出用戶名為" + UserName + "的一條數據失敗");
}
實現步驟10
步驟序號 |
操作步驟 |
檢查點 |
10 |
點擊重置按鈕 |
用戶名為空,用戶類型為“所有”,不勾選時間 |
這一步很簡單,幾乎沒什么說的,只是需要注意的是最好加個等待時間,代碼如下:
{
WinEdit uITbx_UserNameEdit = this.UI查詢用戶Window.UITbx_UserNameWindow.UITbx_UserNameEdit;
WinComboBox uI用戶類型ComboBox = this.UI查詢用戶Window.UICbx_UserTypeWindow.UI用戶類型ComboBox;
WinCheckBox uI日期CheckBox = this.UI查詢用戶Window.UI日期Window.UI日期CheckBox;
WinButton uI重置Button = this.UI查詢用戶Window.UI重置Window.UI重置Button;
//操作步驟
Mouse.Click(uI重置Button, new Point(25, 14));
System.Threading.Thread.Sleep(1000);//等待1秒,應付可能出現的查詢延時
//檢查點:用戶名為空,用戶類型為“所有”,不勾選時間
bool isValid = true;
isValid &= string.IsNullOrEmpty(uITbx_UserNameEdit.Text);
isValid &= uI用戶類型ComboBox.SelectedItem == "所有";
isValid &= !uI日期CheckBox.Checked;
Assert.IsTrue(isValid, "重置失敗");
}
實現步驟11
步驟序號 |
操作步驟 |
檢查點 |
11 |
點擊退出 |
退出窗口 |
這一步也很簡單,和上個部分提到的一樣,代碼如下:
{
Mouse.Click(this.UI查詢用戶Window.UI查詢用戶TitleBar.UICloseButton, new Point(1, 1));
Mouse.Click(this.UI系統主窗口Window.UI系統主窗口TitleBar.UICloseButton, new Point(1, 1));
Assert.IsTrue(this.UI系統主窗口Window.WaitForControlNotExist(3000), "退出失敗");
}
總結
在本章,介紹了通過編碼的方式來建立UI測試,,相信大家在看完了以后,應該能夠完全自己用VS2010提供的UI測試進行實際項目測試了。如果需要調用剛才所寫的方法,只需要再新建一個編碼的UI測試,例如將其命名為CodedUITest1.cs,然后在內部添加一個這樣的調用即可:
public void CodedUITestMethod1()
{
DateTime addTime;
AddUserUIMapClasses.AddUserUIMap addUserUIMap = new AddUserUIMapClasses.AddUserUIMap();
addUserUIMap.Step1_LoginSystem();
addUserUIMap.Step2_ClickAddUser();
addUserUIMap.Step3_AddUserWithNoName();
addUserUIMap.Step4_AddUserWithOverlapName();
addUserUIMap.Step5_AddUserWithNoMemo();
addTime = addUserUIMap.Step6_AddUserSuccess();//這里要特別注意,有一個返回值
addUserUIMap.Step7_CloseWindows();
SearchUserUIMapClasses.SearchUserUIMap searchUserUIMap = new SearchUserUIMapClasses.SearchUserUIMap();
searchUserUIMap.Step1_ClickSearchUser();
searchUserUIMap.Step2_SearchWithOutCondition();
searchUserUIMap.Step3_SearchWithUidOnly();
searchUserUIMap.Step4_SearchWithUidNotExist();
searchUserUIMap.Step5_SearchWithAdminOnly();
searchUserUIMap.Step6_SearchWithNormalUserOnly();
searchUserUIMap.Step7_ValidUserCount();
searchUserUIMap.Step8_SearchWithDateOnly();
searchUserUIMap.Step9_SearchWithAllCondition(addTime);//這里要特別注意,有一個參數
searchUserUIMap.Step10_ClickReset();
searchUserUIMap.Step11_CloseWindow();
}
示例程序的下載:下載點我
個人錄制的源代碼下載:下載點我
在下一章,將會介紹如何建立數據驅動的測試,敬請關注。