每个@Test

时间:2018-11-07 20:00:57

标签: spring-boot junit appium applicationcontext

我正在使用Spring Boot 2.0.1为混合应用创建一个Appium测试框架,而在使用Spring的TestExecutionListeners时遇到了麻烦。

目标:为每个标记有JUnit AppiumDriver<WebElement>的测试初始化​​一个新的@Test实例,并在每次测试后使用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;
    }
}

我通过创建应用的配置实例({.1)},并注册TestScope Bean并为其提供新创建的AppiumDriver<WebElement>,在应用的配置文件(Application.java)中注册"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实例:

@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()时,它清除了TestScope,Spring被迫创建了一个新的驱动程序实例,但是由于某种原因,第一项测试工作正常,而第二项则告诉我该会话是失败的终止。

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驱动程序并且第二次测试正在运行时,从不以某种方式重新注入驱动程序实例,以便它们使用新实例?无论如何,我想看看你们是否知道我在设置错误时计算了我在这里要完成的工作。

0 个答案:

没有答案