package org.uiautomation.ios.e2e.crash; import junit.framework.Assert; import org.openqa.selenium.By; import org.openqa.selenium.WebElement; import org.openqa.selenium.remote.RemoteWebDriver; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import org.uiautomation.ios.IOSCapabilities; import org.uiautomation.ios.SampleApps; import org.uiautomation.ios.server.IOSServer; import org.uiautomation.ios.server.IOSServerConfiguration; import org.uiautomation.ios.utils.ClassicCommands; import java.net.MalformedURLException; import java.net.URL; public class CrashHandling { private IOSServer server; private IOSServerConfiguration config; private RemoteWebDriver driver; private IOSCapabilities cap; @BeforeMethod public void startServer() throws Exception { String[] args = {"-port", "4444", "-host", "localhost", "-app", SampleApps.getPPNQASampleApp(), "-simulators"}; config = IOSServerConfiguration.create(args); server = new IOSServer(config); server.start(); Thread.sleep(1000); cap = SampleApps.ppNQASampleAppCap(); cap.setCapability(IOSCapabilities.SIMULATOR, true); driver = new RemoteWebDriver(getRemoteURL(), cap); } @AfterMethod public void closeDriver() throws Exception { try { if (driver != null) { driver.quit(); driver = null; } } catch (Exception ignored) { } try { if (server != null) { server.stop(); server = null; } } catch (Exception ignored) { } } private URL getRemoteURL() { try { URL remote = new URL("http://" + config.getHost() + ":" + config.getPort() + "/wd/hub"); return remote; } catch (MalformedURLException e) { throw new RuntimeException(e); } } @Test public void isAppCrashDetected() throws InterruptedException { WebElement crashButton = driver.findElement(By.name("Crash me!")); boolean crashExceptionThrown = false; try { crashButton.click(); // give instruments some time to realise there has been a crash and report it Thread.sleep(1000); // the application has crashed - we should be notified on the next client request crashButton.click(); } catch (Exception e) { crashExceptionThrown = true; Assert.assertTrue("Crash error contains the crash trace file details. " + e.getMessage(), e.getMessage().contains("The crash report can be found")); } Assert.assertTrue("App crash detected.", crashExceptionThrown); } @Test public void isExceptionThrownOnEveryActionAfterCrash() throws InterruptedException { WebElement crashButton = driver.findElement(By.name("Crash me!")); crashButton.click(); // give instruments some time to realise there has been a crash and report it Thread.sleep(1000); catchCrashException(crashButton); catchCrashException(crashButton); catchCrashException(crashButton); } private boolean catchCrashException(WebElement button) { boolean crashExceptionThrown = false; try { // the application has crashed - we should be notified on the next client request button.click(); } catch (Exception e) { crashExceptionThrown = true; Assert.assertTrue("Crash error contains the crash trace file details. " + e.getMessage(), e.getMessage().contains("The crash report can be found")); } return crashExceptionThrown; } @Test public void canStartANewSessionAfterAppCrash() throws InterruptedException { WebElement crashButton = driver.findElement(By.name("Crash me!")); try { crashButton.click(); // give instruments some time to realise there has been a crash and report it Thread.sleep(1000); // the application has crashed - we should be notified on the next client request crashButton.click(); } catch (Exception e) { // this is expected since we crashed the app } driver = new RemoteWebDriver(getRemoteURL(), cap); Assert.assertTrue("We can start a new test session", driver != null); } @Test public void isSimulatorCrashDetected() throws InterruptedException { WebElement crashButton = driver.findElement(By.name("Crash me!")); boolean crashExceptionThrown = false; try { // kill simulator ClassicCommands.killall("iPhone Simulator"); Thread.sleep(1000); // should throw an exception crashButton.click(); } catch (Exception e) { crashExceptionThrown = true; Assert.assertTrue("Crash error contains Simulator as likely cause of problem. " + e.getMessage(), e.getMessage().contains("It appears like the Simulator process has crashed")); } Assert.assertTrue("Simulator crash detected.", crashExceptionThrown); } @Test public void canStartANewSessionAfterSimulatorCrash() throws InterruptedException { WebElement crashButton = driver.findElement(By.name("Crash me!")); try { // kill simulator ClassicCommands.killall("iPhone Simulator"); Thread.sleep(1000); // should throw an exception crashButton.click(); } catch (Exception ignored) { // this is expected since we crashed the simulator } driver = new RemoteWebDriver(getRemoteURL(), cap); Assert.assertTrue("We can start a new test session", driver != null); } @Test public void isInstrumentsCrashDetected() throws InterruptedException { WebElement crashButton = driver.findElement(By.name("Crash me!")); boolean crashExceptionThrown = false; try { // kill instruments ClassicCommands.killall("instruments"); Thread.sleep(1000); // should throw an exception crashButton.click(); } catch (Exception e) { crashExceptionThrown = true; Assert.assertTrue("Crash error contains Instruments as likely cause of problem. " + e.getMessage(), e.getMessage().contains("Instruments")); } Assert.assertTrue("Instruments crash detected.", crashExceptionThrown); } @Test public void canStartANewSessionAfterInstrumentsCrash() throws InterruptedException { WebElement crashButton = driver.findElement(By.name("Crash me!")); try { // kill instruments ClassicCommands.killall("instruments"); Thread.sleep(1000); // should throw an exception crashButton.click(); } catch (Exception e) { // this is expected since we crashed instruments } driver = new RemoteWebDriver(getRemoteURL(), cap); Assert.assertTrue("We can start a new test session", driver != null); } }