package com.mumux.androidtesting.runner; import com.android.uiautomator.core.UiDevice; import com.android.uiautomator.testrunner.UiAutomatorTestCase; import com.mumux.androidtesting.actions.Action; import com.mumux.androidtesting.scenario.*; import java.io.File; import java.io.PrintStream; import java.io.Reader; import java.util.ArrayList; import java.util.Date; import java.util.List; /** * Run Scenario pure java * indepdently of Android */ public class ScenarioRunner { private UiAutomatorTestCase uiAutomatorTestCase = null; private final Runtime runtime; private boolean deviceRooted = false; private File outputDir = null; private ScenarioParser scenarioParser = new TextScenarioParser(); private PrintStream out = null; private void debug(String message) { if (out != null) { out.println(new Date() + "|" + message); } } public ScenarioRunner(UiAutomatorTestCase uiAutomatorTestCase, Runtime runtime, boolean deviceRooted, File outputDir) { this.uiAutomatorTestCase = uiAutomatorTestCase; this.runtime = runtime; this.deviceRooted = deviceRooted; this.outputDir = outputDir; } void setScenarioParser(ScenarioParser scenarioParser) { this.scenarioParser = scenarioParser; } public void setPrintStream(PrintStream out) { this.out = out; } public ScenarioTestCase run(Reader reader, int index) { return run(reader, null, index); } private ScenarioTestCase run(Reader reader, PrintStream out, int index) { Scenario scenario; // Parsing Scenario try { scenario = scenarioParser.parse(reader); } catch (ScenarioParsingException e) { ScenarioTestCase testCase2 = new ScenarioTestCase(e.scenarioName, TestStatus.ERROR); testCase2.message = "Invalid Scenario - " + e.getMessage(); return testCase2; } // Pre-Run Check if (scenario.isRootRequired() && !deviceRooted) { ScenarioTestCase testCase2 = new ScenarioTestCase(scenario.name, TestStatus.ERROR); testCase2.message = "Scenario requires a rooted device"; return testCase2; } // Run Scenario TestStatus testStatus = TestStatus.SUCCESS; List<ActionTestCase> actions = new ArrayList<>(); for (Action action : scenario.getActions()) { actions.add(new ActionTestCase(action.toString())); } Long start = System.currentTimeMillis(); boolean continueTest = true; File screenshotsDir = new File(outputDir, "scenario/" + index); boolean status = screenshotsDir.mkdirs(); if (out != null && !status) { out.println("Can not create directory " + screenshotsDir); } takeScreenshot(uiAutomatorTestCase.getUiDevice(), screenshotsDir, 0); for (int i = 0; i < actions.size() && continueTest; i++) { debug("Running " + scenario.getActions().get(i)); String error = scenario.getActions().get(i).run(uiAutomatorTestCase, runtime); if (error == null) { actions.get(i).status = TestStatus.SUCCESS; debug("success"); uiAutomatorTestCase.getUiDevice().waitForIdle(); takeScreenshot(uiAutomatorTestCase.getUiDevice(), screenshotsDir, i + 1); } else { actions.get(i).message = error; actions.get(i).status = TestStatus.FAILURE; debug("failure - " + error); if (!(scenario.getActions().get(i) instanceof OptionalAction)) { continueTest = false; testStatus = TestStatus.FAILURE; } } } ScenarioTestCase testCase = new ScenarioTestCase(scenario.name, testStatus); testCase.actionTestCases = actions; testCase.duration = System.currentTimeMillis() - start; return testCase; } private static void takeScreenshot(UiDevice uiDevice, File outputDir, int step) { File file = new File(outputDir, String.format("%03d.png", step)); System.err.println("take screenshot " + file); uiDevice.takeScreenshot(file); } }