C# 测量自动化测试步骤执行时间

C# 测量自动化测试步骤执行时间,c#,automation,automated-tests,reporting,coded-ui-tests,C#,Automation,Automated Tests,Reporting,Coded Ui Tests,我有10个测试方法,每个方法都有一些自动的业务功能,例如Login()、CreateSomeRecord()、EditSomeRecord()、DeleteSomeRecord()等。 我还有一个HTML报告,它将捕获在测试方法中完成的操作(基本上捕获测试步骤)。大概是这样的: 1. Enter Username: user01 User Entered Successfully Pass 2. Enter Password: pass01 Pass Entered Successf

我有10个测试方法,每个方法都有一些自动的业务功能,例如
Login()、CreateSomeRecord()、EditSomeRecord()、DeleteSomeRecord()等。

我还有一个HTML报告,它将捕获在测试方法中完成的操作(基本上捕获测试步骤)。大概是这样的:

1. Enter Username: user01   User Entered Successfully   Pass
2. Enter Password: pass01   Pass Entered Successfully   Pass
3. Click Login button       Login successful            Pass
// Initializing a new instance of the Stopwatch class
Stopwatch stopWatch = new Stopwatch();
TimeSpan ts;
string elapsedTime;

//Username field
stopWatch.Start();
WpfEdit usrName = new WpfEdit(wpfWndObj);
#region Search Criteria
usrName.SearchProperties[WpfEdit.PropertyNames.AutomationId] = "Usertxt";
usrName.WindowTitles.Add("My Test Application");
#endregion
Keyboard.SendKeys(usrName, usn); //usn has my username value in it
stopWatch.Stop();
ts = stopWatch.Elapsed;
elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
//Writing a new row into my HTML report
RptRowValueAdd(ReportDt, "", "Enter Username: " + usn, "Username Entered Successfully", "Pass", "", elapsedTime);
stopWatch.Reset();
我基本上是从代码一行一行地构造HTML文件。 现在,我想再添加一列,以捕获完成特定步骤所需的持续时间

所以,我在做这样的事情:

1. Enter Username: user01   User Entered Successfully   Pass
2. Enter Password: pass01   Pass Entered Successfully   Pass
3. Click Login button       Login successful            Pass
// Initializing a new instance of the Stopwatch class
Stopwatch stopWatch = new Stopwatch();
TimeSpan ts;
string elapsedTime;

//Username field
stopWatch.Start();
WpfEdit usrName = new WpfEdit(wpfWndObj);
#region Search Criteria
usrName.SearchProperties[WpfEdit.PropertyNames.AutomationId] = "Usertxt";
usrName.WindowTitles.Add("My Test Application");
#endregion
Keyboard.SendKeys(usrName, usn); //usn has my username value in it
stopWatch.Stop();
ts = stopWatch.Elapsed;
elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
ts.Hours, ts.Minutes, ts.Seconds,
ts.Milliseconds / 10);
//Writing a new row into my HTML report
RptRowValueAdd(ReportDt, "", "Enter Username: " + usn, "Username Entered Successfully", "Pass", "", elapsedTime);
stopWatch.Reset();
RptRowValueAdd函数的内容

//DataTable tblObj is a dataset.
//I am writing the report into data-set first before writing it into a HTML file
public void RptRowValueAdd(DataTable tblObj, String TcName, String StepName, String ActRes, String Status, String ScrShtName, String TotalTimer = "", String BeginTimer = "", String EndTimer = "", String TestMethodName = "")
{
    tblObj.NewRow();
    tblObj.Rows.Add(ReportRowValue, TcName, StepName, ActRes, Status, ScrShtName,TotalTimer);
    ReportRowValue = ReportRowValue + 1;
}
这实际上是可行的,但想象一下启动秒表、停止秒表、计算经过的时间然后重置秒表所需的时间。我需要对写入HTML报告文件的每一行执行此操作

当我想到对所有10种测试方法都这样做时,它开始变得麻烦了

有没有更好的编码方法

我不寻找任何基于分析器(ANTS)的解决方案。我知道分析器就是为了这个目的而存在的,但我想知道是否有更好的方法来处理我目前在代码中所做的事情


感谢您的指导。

我想我遗漏了一些细节,例如RptRowValueAdd中发生的事情-您如何知道用户名输入成功以及测试通过?不管怎样,也许这个方法会给你一些想法

拥有一个表示每个测试数据的类:

public class TestDetails
{
    public string TestName { get; set; }
    public string ResultDescription { get; set; }
    public Result TestResult { get; set; }
    public string ElapsedTime { get; set; }

    public TestDetails(string testName, string resultDescription, Result result, string elapsedTime)
    {
        ResultDescription = resultDescription;
        TestResult = result;
        ElapsedTime = elapsedTime;
    }

    public enum Result
    {
        Pass,
        Fail
        // etc
    }
}
然后,创建一个将测试作为操作参数并返回测试细节的方法

    public static TestDetails RunTest(Action testMethod)
    {
        var sw = new Stopwatch();
        TimeSpan ts;
        string elapsedTime;
        sw.Start();
        testMethod.Invoke();
        sw.Stop();
        ts = sw.Elapsed;
        elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);

        return new TestDetails("Enter username: ", "Username entered Successfully", TestDetails.Result.Pass, elapsedTime);
    }
要使用这些方法,您可以创建一个操作方法列表,向其中添加所有测试并在foreach中调用它们:

        var tests = new List<Action>
        (
            Login,
            CreateSomeRecord,
            EditSomeRecord,
            DeleteSomeRecord
        );

        foreach (var test in tests)
        {
            var testDetails = RunTest(test);
            RptRowValueAdd(ReportDt, "", testDetails.TestName, testDetails.ResultDescription, testDetails.TestResult.ToString(), testDetails.ElapsedTime);
        }
var测试=新列表
(
登录,
CreateSomeRecord,
编辑记录,
删除体记录
);
foreach(测试中的var测试)
{
var testDetails=RunTest(测试);
RptRowValueAdd(ReportDt,“,testDetails.TestName,testDetails.ResultDescription,testDetails.TestResult.ToString(),testDetails.ElapsedTime);
}
我希望我没有误解你


谢谢

我想我遗漏了一些细节,比如RptRowValueAdd中发生了什么-您如何知道用户名输入成功并且测试通过了?不管怎样,也许这个方法会给你一些想法

拥有一个表示每个测试数据的类:

public class TestDetails
{
    public string TestName { get; set; }
    public string ResultDescription { get; set; }
    public Result TestResult { get; set; }
    public string ElapsedTime { get; set; }

    public TestDetails(string testName, string resultDescription, Result result, string elapsedTime)
    {
        ResultDescription = resultDescription;
        TestResult = result;
        ElapsedTime = elapsedTime;
    }

    public enum Result
    {
        Pass,
        Fail
        // etc
    }
}
然后,创建一个将测试作为操作参数并返回测试细节的方法

    public static TestDetails RunTest(Action testMethod)
    {
        var sw = new Stopwatch();
        TimeSpan ts;
        string elapsedTime;
        sw.Start();
        testMethod.Invoke();
        sw.Stop();
        ts = sw.Elapsed;
        elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);

        return new TestDetails("Enter username: ", "Username entered Successfully", TestDetails.Result.Pass, elapsedTime);
    }
要使用这些方法,您可以创建一个操作方法列表,向其中添加所有测试并在foreach中调用它们:

        var tests = new List<Action>
        (
            Login,
            CreateSomeRecord,
            EditSomeRecord,
            DeleteSomeRecord
        );

        foreach (var test in tests)
        {
            var testDetails = RunTest(test);
            RptRowValueAdd(ReportDt, "", testDetails.TestName, testDetails.ResultDescription, testDetails.TestResult.ToString(), testDetails.ElapsedTime);
        }
var测试=新列表
(
登录,
CreateSomeRecord,
编辑记录,
删除体记录
);
foreach(测试中的var测试)
{
var testDetails=RunTest(测试);
RptRowValueAdd(ReportDt,“,testDetails.TestName,testDetails.ResultDescription,testDetails.TestResult.ToString(),testDetails.ElapsedTime);
}
我希望我没有误解你


首先,正如我在你的几个问题中指出的,我不会像你所说明的那样驾驶我的考试。您需要测试方法以某种特定的顺序执行。此外,您需要在每种情况下运行断言,即使在验证它们是否正常工作之后也是如此。例如,Enter User Name方法中的所有断言都将在涉及设置用户名的每个业务流程上运行。这种方法无法单独测试登录名。设置用户名的测试通过后,所有其他测试都可以假定它可以工作根据断言的不同,每次执行断言的时间都会显著增加。

也就是说,我将创建一些单独的东西来协调您的测试。此编排类可以具有与每个步骤关联的计时。但是,不清楚您是如何使用计时的(如果有的话)

我的博客涵盖了这一点,但为了突出这一点:

// orchestrates login user action
interface ILoginActions
{
    // logs in the user and returns a reference to the account settings page
    // which appears after successful login
    IAccountSettings Login(string username, string password);
}

public class LoginActions : ILoginActions
{
    public readonly ILoginPage loginPage;
    public LoginActions(ILoginPage loginPage)
    {
        this.loginPage = loginPage;
    }

    public IAccountSettings Login(string username, string password)
    {
        // the orchestrator does not typically need to make assertions,
        // and can assume that there are tests for Login actions
        stopWatch.Start();

        var model = 
        this.loginPage
            .Username.SetValue(username)
            .Password.SetValue(password)
            .Login.Click();

        stopWatch.Stop();

        log("Login Timing", stopWatch.Elapsed);

        return model;
    }
}
重申一下,上述业务流程类的存在是基于这样一种假设,即登录页面存在一整套不使用业务流程类的测试


测试方法中的计时必须按照您已经确定的方式进行,或者与@Mvarta的答案混合进行。

首先,正如我在您的几个问题中指出的,我不会像您所说明的那样驾驶测试。您需要测试方法以某种特定的顺序执行。此外,您需要在每种情况下运行断言,即使在验证它们是否正常工作之后也是如此。例如,Enter User Name方法中的所有断言都将在涉及设置用户名的每个业务流程上运行。这种方法无法单独测试登录名。设置用户名的测试通过后,所有其他测试都可以假定它可以工作根据断言的不同,每次执行断言的时间都会显著增加。

也就是说,我将创建一些单独的东西来协调您的测试。此编排类可以具有与每个步骤关联的计时。但是,不清楚您是如何使用计时的(如果有的话)

我的博客涵盖了这一点,但为了突出这一点:

// orchestrates login user action
interface ILoginActions
{
    // logs in the user and returns a reference to the account settings page
    // which appears after successful login
    IAccountSettings Login(string username, string password);
}

public class LoginActions : ILoginActions
{
    public readonly ILoginPage loginPage;
    public LoginActions(ILoginPage loginPage)
    {
        this.loginPage = loginPage;
    }

    public IAccountSettings Login(string username, string password)
    {
        // the orchestrator does not typically need to make assertions,
        // and can assume that there are tests for Login actions
        stopWatch.Start();

        var model = 
        this.loginPage
            .Username.SetValue(username)
            .Password.SetValue(password)
            .Login.Click();

        stopWatch.Stop();

        log("Login Timing", stopWatch.Elapsed);

        return model;
    }
}
重申一下,上述业务流程类的存在是基于这样一种假设,即登录页面存在一整套不使用业务流程类的测试


测试方法中的计时必须按照您已经确定的方式进行,或者可能与@Mvarta的答案混合进行。

我已经更新了我的问题,以包括RptRowValueAdd func的定义