zoukankan      html  css  js  c++  java
  • 一起谈.NET技术,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的两句代码,以免他在测试结束后将主窗口关闭掉:

    public void 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

    在主窗口菜单点击用户查询

    检测查询用户子窗口是否弹出

      相信这个很简单,两下就可以通过录制然后修改的方式编写出来:

    public void Step1_ClickSearchUser()
    {
    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 int AllUser;//注意,这里留一个字段来保存行数

    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”才算正确,代码如下:

    public void Step3_SearchWithUidOnly()
    {
    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就可以通过测试:

    public void Step4_SearchWithUidNotExist()
    {
    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 int AdminUser;//注意,这里留一个字段来保存管理员用户的行数

    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 int NormalUser;//注意,这里留一个字段来保存一般用户的行数

    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

    使用刚才用户类型分别为“所有”,“管理员”,“一般用户”查询出的数据行数,进行比对

    一般用户行数+管理员用户行数=所有用户行数

      现在应该了解之所以需要记录下不同用户类型记录数的原因了吧?代码如下:

    public void Step7_ValidUserCount()
    {
    Assert.AreEqual(AdminUser
    + NormalUser, AllUser, "检查'一般用户行数+管理员用户行数=所有用户行数'失败");
    }

      实现步骤8

    步骤序号

    操作步骤

    检查点

    8

    用户名为空,用户类型为“所有”,勾选时间,并进行选择“2008-1-11”

    查询出所有添加时间为“2008-1-11”的用户

      步骤8是对时间维度进行一个测试,现在如果我们选择了2008-1-11,那么只需要遍历查询出的各行的“时间”一列是不是为2008-1-11:

    public void Step8_SearchWithDateOnly()
    {
    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,让其有一个返回值返回当前时间,代码如下:

    public DateTime 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;
    }

      然后现在在这里引用之前的变量,来进行操作,代码如下:

    public void Step9_SearchWithAllCondition(DateTime addTime)
    {
    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

    点击重置按钮

    用户名为空,用户类型为“所有”,不勾选时间

      这一步很简单,几乎没什么说的,只是需要注意的是最好加个等待时间,代码如下:

    public void Step10_ClickReset()
    {
    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

    点击退出

    退出窗口

      这一步也很简单,和上个部分提到的一样,代码如下:

    public void Step11_CloseWindow()
    {
    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,然后在内部添加一个这样的调用即可:

    [TestMethod]
    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();
    }

      示例程序的下载:下载点我

      个人录制的源代码下载:下载点我

      在下一章,将会介绍如何建立数据驱动的测试,敬请关注。

  • 相关阅读:
    hdu 1823 Luck and Love 二维线段树
    UVA 12299 RMQ with Shifts 线段树
    HDU 4578 Transformation 线段树
    FZU 2105 Digits Count 线段树
    UVA 1513 Movie collection 树状数组
    UVA 1292 Strategic game 树形DP
    【ACM】hdu_zs2_1003_Problem C_201308031012
    qsort快速排序
    【ACM】nyoj_7_街区最短路径问题_201308051737
    【ACM】nyoj_540_奇怪的排序_201308050951
  • 原文地址:https://www.cnblogs.com/waw/p/2162912.html
Copyright © 2011-2022 走看看