Я создаю среду тестирования Appium для гибридного приложения, используя Spring Boot 2.0.1, и у меня возникают проблемы с использованием Spring TestExecutionListeners.
Цель: Инициализировать новый экземпляр AppiumDriver<WebElement>
для каждого теста, помеченного @Test
JUnit, и завершать эти экземпляры драйвера, используя AppiumDriver quit()
после каждого теста.
Структура моей платформы: Я создал пользовательскую область с именем TestScope
public class TestScope implements Scope {
private Map<String, Object> scopedObjects = Collections.synchronizedMap(new HashMap<String, Object>());
private Map<String, Runnable> destructionCallbacks = Collections.synchronizedMap(new HashMap<String, Runnable>());
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
if (!this.scopedObjects.containsKey(name)) {
this.scopedObjects.put(name, objectFactory.getObject());
}
return this.scopedObjects.get(name);
}
@Override
public String getConversationId() {
return null;
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
this.destructionCallbacks.put(name, callback);
}
@Override
public Object remove(String name) {
this.destructionCallbacks.remove(name);
return this.scopedObjects.remove(name);
}
public void reset() {
this.scopedObjects.clear();
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
}
Я регистрирую TestScope
в файле конфигурации моего приложения (Application.java), создав его единичный экземпляр, а также зарегистрировав мой компонент AppiumDriver<WebElement>
и предоставив ему только что созданную область действия "test"
:
@SpringBootApplication
@PropertySource("classpath:application.properties")
public class Application implements EnvironmentAware {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public CustomScopeConfigurer customScopeConfigurer() {
CustomScopeConfigurer scopeConfigurer = new CustomScopeConfigurer();
Map<String, Object> scopes = new HashMap<>();
scopes.put("test", this.testScope());
scopeConfigurer.setScopes(scopes);
return scopeConfigurer;
}
@Bean
@Scope("test")
public AppiumDriver<WebElement> driver() {
DesiredCapabilities caps = new DesiredCapabilities();
caps.setCapability(MobileCapabilityType.PLATFORM_NAME, this.env.getProperty("platformName"));
caps.setCapability(MobileCapabilityType.PLATFORM_VERSION, this.env.getProperty("platformVersion"));
caps.setCapability(MobileCapabilityType.DEVICE_NAME, this.env.getProperty("deviceName"));
caps.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT,
Integer.parseInt(this.env.getProperty("newCommandTimeout")));
caps.setCapability(MobileCapabilityType.AUTO_WEBVIEW, true);
// Android Capabilities
if (this.env.getProperty("platformName").equals("Android")) {
caps.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, this.env.getProperty("androidAppPackage"));
caps.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, this.env.getProperty("androidAppActivity"));
}
try {
return new AppiumDriver<WebElement>(new URL("http://127.0.0.1:4723/wd/hub"), caps);
} catch (Exception e) {
throw new BeanCreationException("driver", "Failed to create Driver", e);
}
}
@Bean
public TestScope testScope() {
return new TestScope();
}
}
После этого я создаю AbstractTestBase
с правильной аннотацией конфигурации. Мой тест будет выполнен следующим образом: они должны расширять с AbstractTestBase
, чтобы они наследовали конфигурацию, и поэтому их тесты создают новые AppriumDriver
instaces для каждого теста:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = Application.class)
@TestExecutionListeners({ AppiumTestExecutionListener.class, DependencyInjectionTestExecutionListener.class })
public abstract class AbstractTestBase {
@Autowired protected PageObject1 pageObj1;
@Autowired protected PageObject2 pageObj2;
}
Наконец, в AppiumTestExecutionListener
, который я установил в AbstractTestBase
, я написал логику для очистки моего экземпляра TestScope
перед каждым тестом и выхода из экземпляра AppiumDriver после каждого теста, чтобы при beforeTestMethod()
вызывается во 2-м тесте, очищает TestScope, и Spring вынужден создавать новый экземпляр драйвера, но по какой-то причине 1-й тест работает нормально, а второй завершается неудачно, сообщая мне, что сеанс завершен.
public class AppiumTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void afterTestMethod(TestContext testContext) throws Exception {
testContext.getApplicationContext().getBean(AppiumDriver.class).quit();
}
@Override
public void beforeTestMethod(TestContext testContext) throws Exception {
testContext.getApplicationContext().getBean(TestScope.class).reset();
}
}
Не уверен, что так происходит, но кажется, что когда я @Autowire
мой драйвер в моих объектах страницы и 2-й тест запущен, каким-то образом экземпляр драйвера никогда не вводится повторно, чтобы они использовали новый экземпляр? Как бы то ни было, я хотел бы узнать, знаете ли вы, ребята, что я что-то не так, принимая во внимание то, что я пытаюсь сделать здесь.