Предполагается, что вы, ребята, отличаете мобильные действия от веб-действий, регистрируя сообщение с префиксом "Mobile:", и что метод reportLog
всегда вызывается в том же потоке, что и сам метод теста (например, testCaseOnAndroid
). ), мы можем создать кэш, в котором хранится последнее предпринятое действие для данного потока (тестовый случай) при каждом вызове reportLog
Если тестовый случай завершается неудачно и вызывается afterTestCase
, мы можем проверить кэш и получить последнее предпринятое действие для текущего потока (метод, отмеченный @AfterMethod
, обычно вызывается в том же потоке, что и сам метод теста), на основе на котором мы можем теперь решить, нужно ли нам вызывать драйвер, который делает снимок экрана окна браузера, или драйвер, который делает снимок экрана экрана эмулируемого устройства:
public abstract class BaseTest {
/**
* Defines the type of a reported test action.
*/
public enum ReportedActionType {
MOBILE,
WEB
}
private final ConcurrentHashMap<Long, ReportedActionType> lastAttemptedActionCache = new ConcurrentHashMap<>();
@AfterMethod
public void afterTestCase(final ITestResult testResult) {
final Long currentThreadId = currentThread().getId();
final ReportedActionType lastReportedActionType = this.lastAttemptedActionCache.get(currentThreadId);
if (testResult.getStatus() == FAILURE) {
printToConsole(String.format("Test failed while attempting to perform a '%1$s' action. | %2$s",
lastReportedActionType,
testResult.getName()));
try {
if (lastReportedActionType == MOBILE) {
captureEmulatedMobileDevice(testResult);
} else {
captureBrowserWindow(testResult);
}
} catch (final Exception exception) {
exception.printStackTrace();
}
}
// todo: quit web driver (Selenium)
// todo: quit mobile driver (close Appium session)
// irrespective of the state of the test result (success or failure), we need to make sure that we
// remove the cached information, otherwise the cache can get really
// large and this could lead to out of memory problems (we could potentially consider
// using a more sophisticated cache implementation of a 3rd-party library
// that supports time-based eviction, so that even if we forget to remove the
// cached information manually, it gets removed automatically after a fixed amount of time - e.g., 5-10 seconds)
this.lastAttemptedActionCache.remove(currentThreadId);
}
// todo: call the appropriate driver to capture a screenshot of the emulated device
private void captureEmulatedMobileDevice(final ITestResult testResult) {
printToConsole("Screenshot of the emulated mobile device has been captured. | " + testResult.getName());
}
// todo: call the appropriate driver to capture a screenshot of the browser window
private void captureBrowserWindow(final ITestResult testResult) {
printToConsole("Screenshot of the browser has been captured. | " + testResult.getName());
}
public void reportLog(final String message) {
// log the message (to console, to file, etc.)
printToConsole(message);
// the assumption is that the actions within a test case are executed within the same
// thread the test case itself is executed in; as long as this assumption holds, we can cache
// the needed information and fetch it later to perform the needed checks
this.lastAttemptedActionCache.put(currentThread().getId(),
getReportedActionType(message));
}
private ReportedActionType getReportedActionType(final String reportLogMessage) {
return reportLogMessage.toLowerCase()
.trim()
.startsWith("mobile:") ? MOBILE : WEB;
}
// todo: replace this with a proper logger
private void printToConsole(final String message) {
System.out.println(currentThread().getId() + " | " + this.getClass()
.getSimpleName() + " | " + message);
}
}
Более правильное решение было бы очень скорее всего, потребуется изменить сотни / тысячи тестов (что, скорее всего, нежелательно). В идеале шаги (действия) тестового примера должны быть смоделированы более правильно и не только существовать в нашем воображении как «вещи», разделенные вызовами методов reportLog
.
Java - это, в конце концов, OOP язык.