【问题标题】:Is it possible to get the NUnit TestContext MethodName from within an IEnumerable method?是否可以从 IEnumerable 方法中获取 NUnit TestContext MethodName?
【发布时间】:2021-12-22 14:19:54
【问题描述】:

我正在使用 NUnits IEnumerable 尝试在 Nunit SetUpFixture 测试基类中按方法名称返回测试数据(见类底部):

    [SetUpFixture]
    public class TestBase
    {
        private readonly BrowserFactory _factory = new BrowserFactory();
        protected IWebDriver Driver;

        private static ExtentReports _extent;
        private static string _projectPath;
        protected ExtentTest _test;
        private static TestContext testContext;
  
        [OneTimeSetUp]
        public void OneTimeSetUp()
        {
            InitializeReport();
            _test = _extent.CreateTest(TestContext.CurrentContext.Test.Name);
            Driver = _factory.Init(Config.Browser);
            Driver.Manage().Window.Maximize();
            Driver.Manage().Cookies.DeleteAllCookies();
        }

        [TearDown]
        public void TearDown()
        {
            var status = TestContext.CurrentContext.Result.Outcome.Status;
            string testClassName = TestContext.CurrentContext.Test.Name;
            string testMethodName = TestContext.CurrentContext.Test.MethodName;
            var stacktrace = string.IsNullOrEmpty(TestContext.CurrentContext.Result.StackTrace) ? "" : string.Format("{0}", TestContext.CurrentContext.Result.StackTrace);
            Status logstatus;

            switch (status)
            {
                case TestStatus.Failed:
                    logstatus = Status.Fail;
                    Console.WriteLine("Test status is Fail");
                    DateTime time = DateTime.Now;
                    String fileName = "Screenshot_" + time.ToString("h_mm_ss") + ".png";
                    String screenShotPath = Capture(Driver, fileName);
                    _test.Log(Status.Fail, "Fail");
                    _test.Log(Status.Fail, "Snapshot below: " + _test.AddScreenCaptureFromPath("Screenshots\\" + fileName));
                    break;

                case TestStatus.Inconclusive:
                    logstatus = Status.Warning;
                    break;

                case TestStatus.Skipped:
                    logstatus = Status.Skip;
                    break;

                default:
                    logstatus = Status.Pass;
                    Console.WriteLine("Test status is Pass");
                    break;
            }

            _test.Log(logstatus, "Test " + " - " + testMethodName + " Ended with a status of " + logstatus + stacktrace);
        }

        [OneTimeTearDown]
        public void OneTimeTearDown()
        {
            CloseBrowser();     
            _extent.Flush();
        }

        public void CloseBrowser()
        {
            Driver?.Close();
            Driver?.Quit();
            Driver?.Dispose();
        }

        public static IEnumerable<JObject> GetTestData()
        {
            string testMethodName = TestContext.CurrentContext.Test.MethodName;

            JObject[] testDataReturned = GetDataByMethod(testMethodName);

            for (int i = 0; i < testDataReturned.Length; i++)
            {
                yield return testDataReturned[i];
            }
        }

        public static JObject[] GetDataByMethod(string testMethodName)
        {
            return JsonUtils.FetchData(testMethodName);
        }
    }
}

我的问题是,当我运行此代码时,IEnumerable 方法GetTestData() 中的字符串testMethodName 的值为AdhocTestMethod,而不是实际的测试方法字符串LoginTest_E2E

我可以在 OneTimeSetUp()TearDown()(见上文)中很好地获取诸如 MethodName 之类的 TestContext 数据,但无法获取 IEnumerable 中返回的方法名称。

我使用IEnumerable的测试用例如下:

        [Test, TestCaseSource("GetTestData")]
        public void LoginTest_E2E(JObject testData)
        {  
            string loginId = testData["loginId"].Value<string>();
            string password = testData["password"].Value<string>();
            string useCase = testData["useCase"].Value<string>();  
        }

作为参考,我在测试中使用的.json数据文件是:

{
  "LoginTest_E2E": [
    {
      "loginId": "testuser1",
      "password": "password1",
      "useCase": "verify for user 1"
    },
    {
      "loginId": "tesetuser2",
      "password": "password2",
      "useCase": "verify for user 2"
    }
  ]

有谁知道为什么我无法在IEnumerable 方法中获取testMethodName 的字符串值?

这里又是有问题的方法:

public static IEnumerable<JObject> GetTestData()
{
    string testMethodName = TestContext.CurrentContext.Test.MethodName;

    JObject[] testDataReturned = GetDataByMethod(testMethodName);

    for (int i = 0; i < testDataReturned.Length; i++)
    {
        yield return testDataReturned[i];
    }
}

【问题讨论】:

  • 抱歉,从问题中不清楚您的 GetTestData 示例代码在测试中的位置以及如何调用它。请显示从测试中某个既定点开始的代码,例如 TestFixture 或 SetUpFixture。
  • 谢谢@Charlie。我用更多细节更新了我的问题。让我知道你的想法。

标签: c# .net selenium nunit ienumerable


【解决方案1】:

通过添加的信息,很明显您有两个基本问题。

第一个问题

您将TestBase 类用于两个目的:作为SetUpFixture 和作为一个或多个TestFixture 类的基类。这不是 SetUpFixture 的预期使用方式。如果您分析在这种情况下会发生什么,这一点就会变得很清楚。

假设您有一个包含测试的类SomeFixture,与TestBase 在同一个命名空间中。当您运行测试时,会执行以下方法...

  1. TestBase.OneTimeSetUp(作为 SetUpFixture 的一部分)
  2. TestBase.OneTimeSetUp(第二次,作为 Somefixture 的基类)
  3. SomeFixture.OneTimeSetup(如果有的话)
  4. SomeFixture.OneTimeTearDown(同上)
  5. TestBase.OneTimeTearDown(作为基类)
  6. TestBase.OneTimeTearDown(作为 SetUpFixture)

(当然,在第 3 步和第 4 步之间,您的每个方法都会运行,前面是任何 SetUp,后面是任何 TearDown。)

以上是个坏消息,因为OneTimeSetUpOneTimeTearDown 方法在两种不同的上下文中运行了两次:在其中一个中,测试名称为TestBase,而在另一个中为SetUpFixture。 (请记住,NUnit 固定装置被认为是“测试”并且有自己的上下文)

结论:要按设计正确使用 SetUpFixture,它应该是您的 TestFixture 的基类。当然,C# 允许您这样做,因为它对 NUnit 属性的含义一无所知。坦率地说,NUnit 并没有禁止它,因为我们没有人在设计该功能时曾想过以这种方式使用它。如果我们有,可能会进行某种检查并发出错误。

[这是一件奇怪的事情。在SetUpFixture 存在的所有这些年里,我都没有看到这个问题出现过。但在过去的几个月里,我已经看过三遍了。我想知道是否有一些文章或示例展示了这种从SetUpFixture 继承的模式。]

第二个问题

这是导致您的数据不可用的原因。

您的测试用例源位于基类中。没关系,假设您希望从基础派生的所有固定装置使用相同的数据。这里的问题是您试图使用单个测试方法的TestContext 来生成数据。

但该上下文仅在定义测试后创建,并且它是用于创建测试的测试用例源。各个测试只有在它们开始执行后才具有上下文

“AdHocTestMethod”的怪事还有待解释……

曾几何时,如果您尝试访问尚未为测试创建的TestContext,我们会抛出异常。这破坏了某些类型的代码,这些代码在 NUnit V2 中工作并且人们抱怨。因此,现在,当您执行此操作时,我们会即时创建一个临时上下文,并允许旧行为(我不打算在这里指定)继续工作。由于上下文需要一个测试名称,我们给它一个:“AdHocTestMethod”。

您正在(无意中)尝试在创建 TestContext 之前访问它,所以您会得到那个相当奇怪的方法。它可能应该在这种情况下抛出,但它不能,因为这将是一个突破性的变化。

结论:您无法在测试用例源中访问测试方法的上下文,因为您是在夹具本身的上下文中运行并且您正在运行在任何测试执行开始之前。生成测试和数据是发现的一部分,而不是执行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多