【问题标题】:How take screenshot and attach it to Allure report, while using Cucumber and JUnit?如何在使用 Cucumber 和 JUnit 时截取屏幕截图并将其附加到 Allure 报告中?
【发布时间】:2017-04-10 04:57:34
【问题描述】:

我在我的自动化测试项目中使用 Cucumber、Selenium、Java、Maven 和 JUnit 堆栈。

目标是对失败和损坏的测试进行截图。我找到了 Java/Maven/JUnit 堆栈的解决方案:

@Rule
public TestWatcher screenshotOnFailure = new TestWatcher() {
    @Override
    protected void failed(Throwable e, Description description) {
        makeScreenshotOnFailure();
    }

    @Attachment("Screenshot on failure")
    public byte[] makeScreenshotOnFailure() {
        return ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
    }
};

但是,当然它在使用 Cucumber 的情况下不起作用,因为它不使用任何 @Test 方法。

所以,我决定将@Rule 更改为@ClassRule,让它监听任何失败,所以这里是:

@ClassRule
public static TestWatcher screenshotOnFailure = new TestWatcher() {
    @Override
    protected void failed(Throwable e, Description description) {
        makeScreenshotOnFailure();
    }

    @Attachment("Screenshot on failure")
    public byte[] makeScreenshotOnFailure() {
        logger.debug("Taking screenshot");
        return ((TakesScreenshot) Application.getInstance().getWebDriver()).getScreenshotAs(OutputType.BYTES);
    }
};

这个解决方案对我没有帮助。

所以,问题是:“当我在测试项目中使用 Java/Selenium/Cucumber/JUnit/Maven 时,如何在失败时附加屏幕截图?”

【问题讨论】:

  • 我也面临同样的问题。截屏但未在魅力报告中显示为附件。我正在使用 Java+Maven+TestNG+Allure。

标签: java selenium junit cucumber


【解决方案1】:

解决方案就是在定义类中添加以下代码:

@After
public void embedScreenshot(Scenario scenario) {
    if (scenario.isFailed()) {
        try {
            byte[] screenshot = ((TakesScreenshot) Application.getInstance().getWebDriver())
                    .getScreenshotAs(OutputType.BYTES);
            scenario.embed(screenshot, "image/png");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

【讨论】:

    【解决方案2】:

    在 GlobalGlue 中

    public class GlobalGlue {
    
      @Before
      public void before(Scenario scenario) throws Exception {
        CONTEXT.setScenario(scenario);
      }
    
      @After
      public void after() {
        WebDriverUtility.after(getDriver(), CONTEXT.getScenario());
      }
    
    }
    

    创建另一个类 WebDriverUtility 并在该添加方法中:

    public static void after(WebDriver driver, Scenario scenario) {
      getScreenshot(driver, scenario);
      driver.close();
    }
    

    public static void getScreenshot(WebDriver driver, Scenario scenario) {
    if (scenario.isFailed()) {
      final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
      scenario.embed(screenshot, "image/png");
      log.info("Thread: " + Thread.currentThread().getId() + " :: "
          + "Screenshot taken and inserted in scenario report");
    }
    

    }

    主要是当场景失败时,您需要将屏幕截图嵌入场景中:

     final byte[] screenshot = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
     scenario.embed(screenshot, "image/png");
    

    ExecutionContext.java

    import com.google.common.cache.CacheBuilder;
    import com.google.common.cache.CacheLoader;
    import com.google.common.cache.LoadingCache;
    import cucumber.api.Scenario;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.openqa.selenium.WebDriver;
    
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ExecutionException;
    
    /**
     * Maintains one webdriver per scenario and one scenario per thread.
     * Can be used for parallel execution.
     * Assumes that scenarios within one feature are not parallel.
     * Can be rewritten using <code>ThreadLocal</code>.
     *
     * @author dkhvatov
     */
    public enum ExecutionContext {
    
      CONTEXT;
    
      private static final Logger log = LogManager.getLogger(ExecutionContext.class);
    
      private final LoadingCache<Scenario, WebDriver> webDrivers =
        CacheBuilder.newBuilder()
          .build(CacheLoader.from(scenario ->
            WebDriverUtility.createDriver()));
    
      private final Map<String, Scenario> scenarios = new ConcurrentHashMap<>();
    
    
      /**
       * Lazily gets a webdriver for the current scenario.
       *
       * @return webdriver
       */
      public WebDriver getDriver() {
        try {
          Scenario scenario = getScenario();
          if (scenario == null) {
            throw new IllegalStateException("Scenario is not set for context. " +
              "Please verify your glue settings. Either use GlobalGlue, or set " +
              "scenario manually: CONTEXT.setScenario(scenario)");
          }
          return webDrivers.get(scenario);
        } catch (ExecutionException e) {
          log.error("Unable to start webdriver", e);
          throw new RuntimeException(e);
        }
      }
    
      /**
       * Gets scenario for a current thread.
       *
       * @return scenario
       */
      public Scenario getScenario() {
        return scenarios.get(Thread.currentThread().getName());
      }
    
      /**
       * Sets current scenario. Overwrites current scenario in a map.
       *
       * @param scenario scenario
       */
      public void setScenario(Scenario scenario) {
        scenarios.put(Thread.currentThread().getName(), scenario);
      }
    
    }
    

    【讨论】:

    • 抱歉,还有一点不清楚——什么是 CONTEXT 变量?
    • 抱歉,这些东西没有用
    • 您面临的问题是什么?
    • 还是一样 - 报告中没有截图))
    【解决方案3】:

    通过这种方式,您可以将屏幕附加到您的魅力报告中。 还要在你的 pom 文件中使用最新的 allure 版本

    import com.google.common.io.Files;
    import io.qameta.allure.Attachment;
    import org.openqa.selenium.OutputType;
    import org.openqa.selenium.TakesScreenshot;
    import org.openqa.selenium.WebDriver;
    import java.io.File;
    import java.io.IOException;
    
    public class ScreenshotUtils {
        @Attachment(type = "image/png")
        public static byte[] screenshot(WebDriver driver)/* throws IOException */ {
            try {
                File screen = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
                return Files.toByteArray(screen);
            } catch (IOException e) {
                return null;
            }
        }
    }
    

    Pom 文件:

     <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-cucumber4-jvm</artifactId>
            <version>${allure.version}</version>
        </dependency>
    
        <dependency>
            <groupId>io.qameta.allure</groupId>
            <artifactId>allure-junit4</artifactId>
            <version>${allure.version}</version>
            <scope>test</scope>
        </dependency>
    

    【讨论】:

    • 不需要转换为ByteArray,只需要将输出类型提到字节即可。 public byte[] takeScreenshot() { return ((TakesScreenshot) webDriver).getScreenshotAs(OutputType.BYTES); }
    猜你喜欢
    • 1970-01-01
    • 2019-08-16
    • 1970-01-01
    • 1970-01-01
    • 2022-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多