package com.neoranga55.cleanguitestarchitecture.cucumber.steps; import android.app.Instrumentation; import android.os.Build; import android.support.test.InstrumentationRegistry; import android.support.test.espresso.EspressoException; import com.neoranga55.cleanguitestarchitecture.util.SpoonScreenshotAction; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import cucumber.api.Scenario; import cucumber.api.java.After; import cucumber.api.java.Before; import cucumber.api.java.en.Given; import static android.support.test.InstrumentationRegistry.getTargetContext; /** * Class containing generic Cucumber test step definitions not related to specific views */ public class HelperSteps { private static Scenario scenario; @Before public static void before(final Scenario scenario) { HelperSteps.scenario = scenario; grantWritePermissionsForScreenshots(); } public static Scenario getScenario() { return HelperSteps.scenario; } @After public static void after() { if ((HelperSteps.scenario != null) && (HelperSteps.scenario.isFailed())) { takeScreenshot("failed"); } } private static void grantWritePermissionsForScreenshots() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { try { Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); String appPackage = getTargetContext().getPackageName(); instrumentation.getUiAutomation().executeShellCommand("pm grant " + appPackage + " android.permission.READ_EXTERNAL_STORAGE"); instrumentation.getUiAutomation().executeShellCommand("pm grant " + appPackage + " android.permission.WRITE_EXTERNAL_STORAGE"); } catch (Exception e) { throw new RuntimeException( "Exception while granting external storage access to application apk", e); } } } /** * Take a screenshot of the current activity and embed it in the HTML report * * @param tag Name of the screenshot to include in the file name */ public static void takeScreenshot(final String tag) { if (scenario == null) { throw new ScreenshotException("Error taking screenshot: I'm missing a valid test scenario to attach the screenshot to"); } SpoonScreenshotAction.perform(tag); final File screenshot = SpoonScreenshotAction.getLastScreenshot(); if (screenshot == null) { throw new ScreenshotException("Screenshot was not taken correctly, check for failures in screenshot library"); } FileInputStream screenshotStream = null; try { screenshotStream = new FileInputStream(screenshot); final byte fileContent[] = new byte[(int) screenshot.length()]; final int readImageBytes = screenshotStream.read(fileContent); // Read data from input image file into an array of bytes if (readImageBytes != -1) { scenario.embed(fileContent, "image/png"); // Embed the screenshot in the report under current test step } } catch (final IOException ioe) { throw new ScreenshotException("Exception while reading file " + ioe); } finally { try { // close the streams using close method if (screenshotStream != null) { screenshotStream.close(); } } catch (final IOException ioe) { //noinspection ThrowFromFinallyBlock throw new ScreenshotException("Error while closing screenshot stream: " + ioe); } } } @Given("^I take a screenshot$") public void i_take_a_screenshot() { takeScreenshot("screenshot"); } public static class ScreenshotException extends RuntimeException implements EspressoException { private static final long serialVersionUID = -1247022787790657324L; ScreenshotException(final String message) { super(message); } } }