All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.testobject.appium.junit.TestObjectAppiumSuite Maven / Gradle / Ivy

There is a newer version: 0.2.7
Show newest version
package org.testobject.appium.junit;

import com.google.common.base.Optional;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.Suite;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.RunnerScheduler;
import org.testobject.appium.junit.internal.Util;
import org.testobject.rest.api.RestClient;
import org.testobject.rest.api.appium.common.Env;
import org.testobject.rest.api.appium.common.TestObject;
import org.testobject.rest.api.appium.common.data.SuiteReport;
import org.testobject.rest.api.appium.common.data.Test;
import org.testobject.rest.api.resource.AppiumSuiteReportResource;
import org.testobject.rest.api.resource.AppiumSuiteResource;

import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TestObjectAppiumSuite extends Suite {

	private class PerDeviceRunner extends BlockJUnit4ClassRunner {

		private final String deviceId;

		public PerDeviceRunner(Class clazz, String deviceId) throws InitializationError {
			super(clazz);
			this.deviceId = deviceId;
		}

		@Override
		protected Description describeChild(FrameworkMethod method) {
			return Description
					.createTestDescription(getTestClass().getJavaClass(), testName(method) + "[" + deviceId + "]", method.getAnnotations());
		}

		@Override
		protected List getTestRules(Object target) {
			List testRules = super.getTestRules(target);
			for (TestRule testRule : testRules) {
				if (testRule instanceof TestObjectTestResultWatcher) {
					TestObjectTestResultWatcher resultWatcher = (TestObjectTestResultWatcher) testRule;
					resultWatcher.configureForSuiteExecution(testObjectApiKey, testObjectSuiteId, suiteReport);
				}
			}

			return testRules;
		}

		@Override
		protected String getName() {
			return super.getName() + "[" + deviceId + "]";
		}

	}

	protected static class ThreadPoolScheduler implements RunnerScheduler {

		private final int timeout;
		private final TimeUnit timeoutUnit;

		private final ExecutorService executor;

		public ThreadPoolScheduler(int numberOfThreads, int timeout, TimeUnit timeoutUnit) {
			this.timeout = timeout;
			this.timeoutUnit = timeoutUnit;

			executor = Executors.newFixedThreadPool(numberOfThreads);
		}

		public void schedule(final Runnable childStatement) {
			executor.submit(childStatement);
		}

		public void finished() {
			executor.shutdown();
			try {
				executor.awaitTermination(timeout, timeoutUnit);
			} catch (InterruptedException exc) {
				throw new RuntimeException(exc);
			}
		}
	}

	private static final List NO_RUNNERS = Collections.emptyList();

	private static final int timeoutDefault = 60;
	private static final TimeUnit timeunitDefault = TimeUnit.MINUTES;

	private final RestClient client;
	private final List perDeviceRunners;

	private String testObjectApiKey;
	private long testObjectSuiteId;
	private Optional testObjectAppId;
	private String[] testObjectDeviceIds;

	private boolean runLocally;

	private SuiteReport suiteReport;

	public TestObjectAppiumSuite(Class clazz) throws InitializationError {
		super(clazz, NO_RUNNERS);

		TestObject config = getConfig(clazz);

		Optional runLocallyFromEnvironment = Env.isTestLocally();
		runLocally = runLocallyFromEnvironment.isPresent() ? Boolean.valueOf(runLocallyFromEnvironment.get()) : config.testLocally();

		if (runLocally) {

			this.client = null;

			Set deviceIds = getLocalDeviceId();

			this.perDeviceRunners = toRunners(clazz, deviceIds);

			this.setScheduler(new ThreadPoolScheduler(deviceIds.size(), timeoutDefault, timeunitDefault));

		} else {

			Optional endpointFromEnvironment = Env.getApiEndpoint();
			String testObjectApiEndpoint = endpointFromEnvironment.isPresent() ? endpointFromEnvironment.get() : config.testObjectApiEndpoint();

			Optional apiKeyFromEnvironment = Env.getApiKey();
			testObjectApiKey = apiKeyFromEnvironment.isPresent() ? apiKeyFromEnvironment.get() : config.testObjectApiKey();

			Optional suiteIdFromEnvironment = Env.getSuiteId();
			testObjectSuiteId = suiteIdFromEnvironment.isPresent() ? Long.parseLong(suiteIdFromEnvironment.get()) : config.testObjectSuiteId();

			Optional appIdFromEnvironment = Env.getAppId();
			Optional appIdFromAnnotation = config.testObjectAppId() != 0 ? Optional.of(Long.toString(config.testObjectAppId())) : Optional.absent();
			testObjectAppId = appIdFromEnvironment.isPresent() ? appIdFromEnvironment : appIdFromAnnotation;

			Optional deviceIdsFromEnvironment = Env.getDevicesIds();
			testObjectDeviceIds = deviceIdsFromEnvironment.isPresent() ? deviceIdsFromEnvironment.get().split(", ") : config.testObjectDeviceIds();

			Optional timeoutFromEnvironment = Env.getTimeout();
			int testObjectTimeout = timeoutFromEnvironment.isPresent() ?  Integer.parseInt(timeoutFromEnvironment.get()) : config.timeout();

			this.client = RestClient.Builder.createClient()
					.withUrl(testObjectApiEndpoint)
					.withToken(testObjectApiKey)
					.path(RestClient.REST_APPIUM_PATH)
					.build();

			Set deviceIds;
			if (testObjectDeviceIds.length == 0) {
				deviceIds = getRemoteDeviceIds();
			} else {
				deviceIds = new HashSet(Arrays.asList(testObjectDeviceIds));
			}

			this.perDeviceRunners = toRunners(clazz, deviceIds);

			this.setScheduler(new ThreadPoolScheduler(deviceIds.size(), testObjectTimeout, config.timeoutUnit()));

		}
	}

	@Override
	public void run(RunNotifier notifier) {
		Set tests = getTests(getDescription());

		if (runLocally) {

			super.run(notifier);

		} else {

			AppiumSuiteReportResource suiteReportResource = new AppiumSuiteReportResource(client);
			try {
				this.suiteReport = suiteReportResource.startSuiteReport(testObjectSuiteId, testObjectAppId, tests);
				try {
					super.run(notifier);
				} finally {
					suiteReportResource.finishSuiteReport(testObjectSuiteId, suiteReport.getId());
				}
			} finally {
				client.close();
			}

		}
	}

	protected List getChildren() {
		return this.perDeviceRunners;
	}

	private static TestObject getConfig(Class clazz) {
		TestObject testobject = clazz.getAnnotation(TestObject.class);
		if (testobject == null) {
			throw new IllegalStateException("class " + clazz + " must be annotated with " + TestObject.class.getName());
		}

		return testobject;
	}

	private Set getRemoteDeviceIds() {
		if (testObjectDeviceIds != null && testObjectDeviceIds.length > 0) {
			return new HashSet(Arrays.asList(testObjectDeviceIds));
		}

		AppiumSuiteResource suiteReportResource = new AppiumSuiteResource(client);
		Set deviceIds = suiteReportResource.readSuiteDeviceIds(testObjectSuiteId);

		return deviceIds;
	}

	private Set getLocalDeviceId() {
		return new HashSet(Collections.singletonList("Local_device"));
	}

	private List toRunners(Class clazz, Set deviceIds) throws InitializationError {
		List runners = new ArrayList(deviceIds.size());
		for (String deviceId : deviceIds) {
			runners.add(new PerDeviceRunner(clazz, deviceId));
		}
		return runners;
	}

	private static Set getTests(Description description) {
		Set tests = new HashSet();
		for (Description childDescription : description.getChildren()) {
			for (Description testDescription : childDescription.getChildren()) {
				tests.add(Util.from(testDescription));
			}
		}

		return tests;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy