【问题标题】:Take screenshot on test failure + exceptions对测试失败 + 异常进行截图
【发布时间】:2016-01-24 02:04:19
【问题描述】:

你们中有人知道对测试失败和异常进行截图的可能解决方案吗?

我在TearDown() 中添加了以下代码,但结果它也会对通过的测试进行截图,所以这不是最好的解决方案:

DateTime time = DateTime.Now;
string dateToday = "_date_" + time.ToString("yyyy-MM-dd") + "_time_" + time.ToString("HH-mm-ss");
Screenshot screenshot = ((ITakesScreenshot)driver).GetScreenshot();
screenshot.SaveAsFile((settings.filePathForScreenShots + "Exception" + dateToday + ".png"), System.Drawing.Imaging.ImageFormat.Png);

我已经找到了这个想法:http://yizeng.me/2014/02/08/take-a-screenshot-on-exception-with-selenium-csharp-eventfiringwebdriver/,使用WebDriverExceptionEventArgs,但由于某些原因,它也制作了一些随机截图,没有任何合理的解释。

我发现的其他想法是针对 Java 而不是针对我与 Selenium 一起使用的 NUnit,因此它们毫无用处。

【问题讨论】:

    标签: c# .net unit-testing selenium nunit


    【解决方案1】:

    如果你将截图逻辑放在你的 TearDown 方法中,它将在每次测试完成后被调用,无论它是成功还是失败。

    我使用了一个基类,它有一个包装测试并捕获所有异常的函数。当测试失败时,将捕获异常并截取屏幕截图。

    我将这个基类用于我所有的 Selenium 测试,它看起来像这样:

    public class PageTestBase
    {
        protected IWebDriver Driver;
    
        protected void UITest(Action action)
        {
            try
            {
                action();
            }
            catch (Exception ex)
            {
                var screenshot = Driver.TakeScreenshot();
    
                var filePath = "<some appropriate file path goes here>";
    
                screenshot.SaveAsFile(filePath, ImageFormat.Png);
    
                // This would be a good place to log the exception message and
                // save together with the screenshot
    
                throw;
            }
        }
    }
    

    测试类如下所示:

    [TestFixture]
    public class FooBarTests : PageTestBase
    {
        // Make sure to initialize the driver in the constructor or SetUp method,
        // depending on your preferences
    
        [Test]
        public void Some_test_name_goes_here()
        {
            UITest(() =>
            {
                // Do your test steps here, including asserts etc.
                // Any exceptions will be caught by the base class
                // and screenshots will be taken
            });
        }
    
        [TearDown]
        public void TearDown()
        {
            // Close and dispose the driver
        }
    }
    

    【讨论】:

    • 如果您能捕获测试的名称并将其包含在屏幕截图的文件名中,那就太好了。但我不明白如何使用这种方法来做到这一点?
    • @FrankH。在此示例中,您应该能够通过 UITest 方法中的反射来实现。由于 UITest 方法是从测试方法中调用的,因此您应该能够从 UITest 方法中获取调用方法的名称。尝试以下方式:stackoverflow.com/questions/171970/…
    • 您确定您的异常正确地记录了行号吗?它是否从正确的程序集中记录异常?我们做了类似的事情,但由于使用包装器时 AssemblyInfo 不同,所以丢失了行号。澄清一下,我们得到了带有正确消息的异常记录,但是行号信息丢失并且始终为 0。您的情况是否相同?
    【解决方案2】:

    在 C# 中,我使用 NUnit 3.4。这提供了OneTimeTearDown 方法,该方法能够访问TestContext,包括先前执行的测试的状态。不要使用TearDown,因为它不会在测试失败后执行;)

    using OpenQA.Selenium;
    using System.Drawing.Imaging;
    
    ...
    
    [OneTimeTearDown]
    public void OneTimeTearDown()
    {
        if (TestContext.CurrentContext.Result.Outcome != ResultState.Success)
        {
            var screenshot = ((ITakesScreenshot)driver).GetScreenshot();
            screenshot.SaveAsFile(@"C:\TEMP\Screenshot.jpg", ImageFormat.Jpeg);
        }
    }
    

    【讨论】:

    • 只要任何SetUp方法运行无误,TearDown方法就保证运行。 Source。我刚刚找到了您的答案,并在 TearDown 中使用了 if 语句,没有任何问题。不过,IMO 这应该是公认的答案。
    • 如果我错了,请纠正我,但我认为在夹具中的所有测试完成后,OneTimeTearDown 是only executed。所以任何截图都为时已晚。
    • 我同意 Trailmax。当其他东西或其他一些测试点击其他东西时,捕捉已经太晚了。它应该在 catch 块中完成,我喜欢顶部示例中的全局 try catch 示例,此外您可以在扩展方法中使用它。
    【解决方案3】:

    为了更公平,这里是 MSTest 的代码

    public TestContext TestContext { get; set; }
    
    [TestCleanup]
    public void TestCleanup()
    {
      if (TestContext.CurrentTestOutcome == UnitTestOutcome.Failed)
      {
        var screenshotPath = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss.fffff}.png";
        MyDriverInstance.TakeScreenshot().SaveAsFile(screenshotPath);
        TestContext.AddResultFile(screenshotPath);
      }
    }
    

    【讨论】:

      【解决方案4】:

      您可以在 TestNG 套件文件中轻松实现此目的 创建如下所示的 ScreenShot 方法

      public static void CaptureDesktop (String imgpath)
          {
              try
              {
      
                  Robot robot = new Robot();
                  Dimension screensize=Toolkit.getDefaultToolkit().getScreenSize();
                  Rectangle screenRect = new Rectangle(screensize);
                  BufferedImage screenshot = robot.createScreenCapture(screenRect);
                  //RenderedImage screenshot = robot.createScreenCapture(screenRect);
              ImageIO.write(screenshot, "png" , new File(imgpath));
      
              }
      

      在上面的方法中,我使用了机器人类,这样你就可以截屏 Dekstop(window+WebPage) 并且你可以在不同的 Listener 类中调用这个方法将实现 ITestListener 接口。在该侦听器类的 OntestFailure() 中调用您的屏幕截图方法

      @Override
          public void onTestFailure(ITestResult arg0) {
      
      
              String methodname = arg0.getMethod().getMethodName();
              String imgpath = "./Screenshot/"+methodname+".jpg";
              Guru99TakeScreenshot.CaptureDesktop(imgpath);
      
          }
      

      此代码对我有用。但是这段代码是用 JAVA 编写的。我希望这将在 C# 中工作,如果不是我希望这段代码可以帮助你

      【讨论】:

        【解决方案5】:

        自定义一点 ExtentReport 可以提供非常有用的报告,在测试失败时准确捕获异常+屏幕截图。屏幕截图可以放在异常旁边,用户可以使用它来了解发生错误时网站在做什么。

        报告示例

        测试

            @Test (enabled=true)                           
        public void verifySearch() {
            extentlogger = extent.createTest("To verify verifySearch");
            //Your other code here.....
            soft.assertEquals("xxx", "xxxx");
            soft.assertAll();
           }
        

        后方法

             @AfterMethod
        public void getResult(ITestResult result) throws Exception{
            if(result.getStatus() == ITestResult.FAILURE)
            {
                extentlogger.log(Status.FAIL, MarkupHelper.createLabel(result.getThrowable() + " - Test Case Failed", ExtentColor.RED));
                
                try {
             // get path of captured screenshot using custom failedTCTakeScreenshot method
                    String screenshotPath = failedTCTakeScreenshot( result);
                    extentlogger.fail("Test Case Failed Snapshot is below " + extentlogger.addScreenCaptureFromPath(screenshotPath));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        

        【讨论】:

        • 你从哪里得到extent 对象?
        猜你喜欢
        • 2015-12-27
        • 1970-01-01
        • 1970-01-01
        • 2016-06-22
        • 2021-07-31
        • 1970-01-01
        • 1970-01-01
        • 2012-12-10
        • 1970-01-01
        相关资源
        最近更新 更多