Не може да се използва HtmlUnitDriver в теста на Geb-Spock Grails поради проблеми със зависимостите

Опитвам се да използвам HtmlUnitDriver във функционален тест на Geb-Spock в Grails 2.3.7. Създавам проект с помощта на Maven.

Когато стартирам тест с този драйвер, получавам:

java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal

Мисля, че получавам тази грешка, защото трябваше да изключа xml-apis:

<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-htmlunit-driver</artifactId>
    <version>2.41.0</version>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>xml-apis</groupId>
            <artifactId>xml-apis</artifactId>
        </exclusion>
    </exclusions>
</dependency>

Но трябваше да го направя, защото в противен случай, когато стартирам maven и се стартират модулни тестове, получавам грешка:

Fatal error forking Grails JVM: java.lang.reflect.InvocationTargetException
java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at org.grails.launcher.GrailsLauncher.launch(GrailsLauncher.java:150)
    at org.grails.maven.plugin.tools.ForkedGrailsRuntime.main(ForkedGrailsRuntime.java:168)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.grails.launcher.GrailsLauncher.launch(GrailsLauncher.java:144)
... 1 more
Caused by: java.lang.LinkageError: loader constraint violation: when resolving overridden method "org.apache.tools.ant.helper.ProjectHelper2$RootHandler.setDocumentLocator(Lorg/xml/sax/Locator;)V" the class loader (instance of org/grails/launcher/RootLoader) of the current class, org/apache/tools/ant/helper/ProjectHelper2$RootHandler, and its superclass loader (instance of <bootloader>), have different Class objects for the type andler.setDocumentLocator(Lorg/xml/sax/Locator;)V used in the signature
at org.apache.tools.ant.helper.ProjectHelper2.parseUnknownElement(ProjectHelper2.java:131)
at org.apache.tools.ant.helper.ProjectHelper2.parseAntlibDescriptor(ProjectHelper2.java:111)
at org.apache.tools.ant.taskdefs.Antlib.createAntlib(Antlib.java:91)
at org.apache.tools.ant.taskdefs.Definer.loadAntlib(Definer.java:440)
at org.apache.tools.ant.taskdefs.Definer.execute(Definer.java:292)
at org.apache.tools.ant.ComponentHelper.checkNamespace(ComponentHelper.java:877)
at org.apache.tools.ant.ComponentHelper.getDefinition(ComponentHelper.java:308)
at org.apache.tools.ant.ComponentHelper.createComponent(ComponentHelper.java:285)
at org.apache.tools.ant.ComponentHelper.createComponent(ComponentHelper.java:264)
at org.apache.tools.ant.UnknownElement.makeObject(UnknownElement.java:417)
at org.apache.tools.ant.UnknownElement.maybeConfigure(UnknownElement.java:163)
at groovy.util.AntBuilder.performTask(AntBuilder.java:314)
at groovy.util.AntBuilder.nodeCompleted(AntBuilder.java:264)
at groovy.util.BuilderSupport.doInvokeMethod(BuilderSupport.java:147)
at groovy.util.AntBuilder.doInvokeMethod(AntBuilder.java:203)
at groovy.util.BuilderSupport.invokeMethod(BuilderSupport.java:64)
at org.codehaus.gant.GantBuilder.invokeMethod(GantBuilder.java:99)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:45)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at org.codehaus.gant.GantBinding.initializeGantBinding(GantBinding.groovy:108)
at org.codehaus.gant.GantBinding.<init>(GantBinding.groovy:42)
at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeScriptWithCaching(GrailsScriptRunner.java:428)
at org.codehaus.groovy.grails.cli.GrailsScriptRunner.callPluginOrGrailsScript(GrailsScriptRunner.java:414)
at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeCommand(GrailsScriptRunner.java:378)
at org.codehaus.groovy.grails.cli.GrailsScriptRunner.executeCommand(GrailsScriptRunner.java:345)
... 6 more

Така че мисля, че това са някакви проблеми със зависимостта. Но не съм сигурен как да се справя. Опитах се да анализирам дървото на зависимостите, но не съм сигурен как да проверя кой иска това org/xml/sax/Locator или org/w3c/dom/ElementTraversal.

Опитах се да изключа повече от само xml-apis от HtmlUnitDriver, също xalan и xerces, но не помогна.

pom.xml изглежда така:

...
<properties>
    <grails.version>2.3.7</grails.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <h2.version>1.3.170</h2.version>
    <gebVersion>0.7.2</gebVersion>
    <seleniumVersion>2.41.0</seleniumVersion>
    <spockVersion>0.7</spockVersion>
    <gebSpockVersion>0.9.0-RC-1</gebSpockVersion>
</properties>

<dependencies>
    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-async</artifactId>
        <version>${grails.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.grails.plugins</groupId>
                <artifactId>spock</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-rest</artifactId>
        <version>${grails.version}</version>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-services</artifactId>
        <version>${grails.version}</version>
    </dependency>
    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-i18n</artifactId>
        <version>${grails.version}</version>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-databinding</artifactId>
        <version>${grails.version}</version>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-filters</artifactId>
        <version>${grails.version}</version>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-gsp</artifactId>
        <version>${grails.version}</version>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-log4j</artifactId>
        <version>${grails.version}</version>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-servlets</artifactId>
        <version>${grails.version}</version>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-url-mappings</artifactId>
        <version>${grails.version}</version>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-resources</artifactId>
        <version>${grails.version}</version>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-test</artifactId>
        <version>${grails.version}</version>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.grails.plugins</groupId>
                <artifactId>spock</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.grails</groupId>
        <artifactId>grails-plugin-testing</artifactId>
        <version>${grails.version}</version>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.grails.plugins</groupId>
                <artifactId>spock</artifactId>
            </exclusion>
        </exclusions>
    </dependency>


    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>${h2.version}</version>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>org.grails.plugins</groupId>
        <artifactId>cache</artifactId>
        <version>1.1.1</version>
        <scope>compile</scope>
        <type>zip</type>
    </dependency>

    <dependency>
        <groupId>org.grails.plugins</groupId>
        <artifactId>hibernate</artifactId>
        <version>3.6.10.9</version>
        <scope>runtime</scope>
        <type>zip</type>
    </dependency>

    <dependency>
        <groupId>org.grails.plugins</groupId>
        <artifactId>database-migration</artifactId>
        <version>1.3.8</version>
        <scope>runtime</scope>
        <type>zip</type>
    </dependency>

    <dependency>
        <groupId>org.grails.plugins</groupId>
        <artifactId>jquery</artifactId>
        <version>1.11.0.2</version>
        <scope>runtime</scope>
        <type>zip</type>
    </dependency>

    <dependency>
        <groupId>org.grails.plugins</groupId>
        <artifactId>jquery-ui</artifactId>
        <version>1.10.3</version>
        <scope>runtime</scope>
        <type>zip</type>
    </dependency>

    <dependency>
        <groupId>org.grails.plugins</groupId>
        <artifactId>resources</artifactId>
        <version>1.2.7</version>
        <scope>runtime</scope>
        <type>zip</type>
    </dependency>

    <dependency>
        <groupId>org.grails.plugins</groupId>
        <artifactId>tomcat</artifactId>
        <version>7.0.52.1</version>
        <scope>provided</scope>
        <type>zip</type>
    </dependency>

    <dependency>
        <groupId>org.grails.plugins</groupId>
        <artifactId>spock</artifactId>
        <version>${spockVersion}</version>
        <scope>test</scope>
        <type>zip</type>
    </dependency>

    <dependency>
        <groupId>org.grails.plugins</groupId>
        <artifactId>geb</artifactId>
        <version>${gebVersion}</version>
        <scope>test</scope>
        <type>zip</type>
    </dependency>

    <dependency>
        <groupId>org.gebish</groupId>
        <artifactId>geb-spock</artifactId>
        <version>${gebSpockVersion}</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.spockframework</groupId>
        <artifactId>spock-grails-support</artifactId>
        <version>0.7-groovy-1.8</version>
    </dependency>

    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-htmlunit-driver</artifactId>
        <version>${seleniumVersion}</version>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>xalan</groupId>
                <artifactId>xalan</artifactId>
            </exclusion>
            <exclusion>
                <groupId>xml-apis</groupId>
                <artifactId>xml-apis</artifactId>
            </exclusion>
            <exclusion>
                <groupId>xerces</groupId>
                <artifactId>xercesImpl</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-chrome-driver</artifactId>
        <version>${seleniumVersion}</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-firefox-driver</artifactId>
        <version>${seleniumVersion}</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-support</artifactId>
        <version>${seleniumVersion}</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.apache.solr</groupId>
        <artifactId>solr-solrj</artifactId>
        <version>4.3.0</version>
        <exclusions>
            <exclusion>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.2.5</version>
    </dependency>
    <dependency>
        <groupId>commons-httpclient</groupId>
        <artifactId>commons-httpclient</artifactId>
        <version>3.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.2.5</version>
    </dependency>
    <dependency>
        <groupId>org.tuckey</groupId>
        <artifactId>urlrewritefilter</artifactId>
        <version>4.0.3</version>
    </dependency>

    <dependency>
        <groupId>co.freeside</groupId>
        <artifactId>betamax</artifactId>
        <version>1.1.2</version>
        <scope>test</scope>
    </dependency>

Ще бъда благодарен за всякакви забележки относно разрешаването на този проблем.

Редактиране

Опитах версии, предложени от erdi, така че:

selenium-htmlunit-driver  2.26.0
                     geb  0.9.0-RC-1
               geb-spock  0.9.0-RC-1
              (and spock  0.7)

Получавам грешката:

2014-05-23 14:37:06,008 [main] ERROR javascript.StrictErrorReporter  
- runtimeError: message=[The data necessary to complete this operation 
is not yet available.] 
sourceName=[http://localhost:8080/search-web-app/static/plugins/jquery-1.11.0.2/js/jquery/jquery-1.11.0.min.js] line=[2] lineSource=[null] lineOffset=[0]

Firefox и Chrome драйверите работят добре (тестовете са преминали). Причината, поради която бих искал драйверът HtmlUnit да работи, е, че искаме да можем да изпълняваме тестове на сървъра на Jenkins. Доколкото разбирам, HtmlUnit е този, който го позволява, защото не отваря браузъра (моля, поправете ме, ако го разбирам погрешно).


person nuoritoveri    schedule 19.05.2014    source източник
comment
Това, което обикновено правя, когато трябва да стартирам тестовете на браузъра си в CI, е да стартирам истински браузър заедно с Xvfb като виртуален дисплей.   -  person erdi    schedule 26.05.2014
comment
Благодаря за обяснението, в крайна сметка използвах PhantomJS за това. По-бавен е от другите драйвери, така че трябваше да добавя waitFor{...}, за да работи, но иначе е добре.   -  person nuoritoveri    schedule 26.05.2014


Отговори (1)


Най-новата версия на HtmlUnitDriver, която успях да стартирам с Grails, е 2.26.0. Както и да е, наистина трябва да избягвате използването на HtmlUnitDriver, тъй като не работи добре с по-сложни уеб страници. Почти винаги е по-добре да управлявате истински браузър в тестовете си.

Моля, обърнете внимание, че най-новата версия на Geb е 0.9.2 и че не трябва да използвате различни версии за geb-spock и приставката Grails Geb (0.9.0-RC-1 и 0.7.2).

person erdi    schedule 21.05.2014