appium / java-client

Java language binding for writing Appium Tests, conforms to W3C WebDriver Protocol
Apache License 2.0
1.22k stars 757 forks source link

java.lang.ClassCastException: com.google.common.collect.Maps$TransformedEntriesMap cannot be cast to java.lang.String #1510

Open RSM-SBA opened 3 years ago

RSM-SBA commented 3 years ago

Description

I use the image comparison feature of appium and since last update of appium, saving the comparison result picture when a failure occure is broken and throws an exception. The comparison itself does work correctly. It throws the ecception on this function

res.storeVisualization(failViz);

I have checked the code in github and it looks like that in the class "ComparisonResult.java" line 63 a map is casted to String.

    return ((String) getCommandResult().get(VISUALIZATION)).getBytes(StandardCharsets.UTF_8);

Environment

Details

Please provide more details, if necessary.

Code To Reproduce Issue [ Good To Have ]

public static void doVisualCheckByELement(String locatorType, String locator, String checkName, double MATCH_THRESHOLD, String baseline) throws Exception {
        waitTime(1000);
        final String dir = System.getProperty("user.dir");
        File VALIDATION_PATH = new File(dir+"/src/test/resources/TestData/compareScrn");
        // File VALIDATION_ERROR_PATH = new File(dir+"/src/test/resources/TestData/compareScrn");
        File f = new File(dir+"/appium_screenshots/"+NameOfClass);
        File folder = new File(dir+"/appium_screenshots");

        try
        {
            if(folder.mkdir()) 
            { 
                sysLogger("debug", "Appium_screenshots Directory Created for screenComparison Failures");
            } 
            else 
            {
                sysLogger("debug", "Appium_screenshots Directory is not created for screenComparison Failures");
            }
        } catch(Exception e)
        {
            e.printStackTrace();
        } 
        try
        {
            if(f.mkdir()) 
            { 
                sysLogger("debug", "Directory Created for screenComparison Failures");
            } 
            else 
            {
                sysLogger("debug", "Directory is not created for screenComparison Failures");
            }
        } catch(Exception e)
        {
            e.printStackTrace();
        } 

        String baselineFilename = VALIDATION_PATH + "/" + NameOfClass+"_"+baseline +"_"+ checkName + ".png";
        File baselineImg = new File(baselineFilename);
        // If no baseline image exists for this check, we should create a baseline image

        if (!baselineImg.exists()) {
        sysLogger("debug", String.format("No baseline found for '%s' check; capturing baseline instead of checking", checkName));
        File newBaseline = TestFlow.driver.getScreenshotAs(OutputType.FILE);
        MobileElement element = (MobileElement) Helpers.find(locatorType, locator, 3, false);
        BufferedImage newBase= Helpers.generateImage(element, newBaseline);
        File outputfile = new File(baselineFilename);
        ImageIO.write(newBase, "png", outputfile);      // FileUtils.copyFile(newBase, new File(baselineFilename));
        return;
        }

        // Otherwise, if we found a baseline, get the image similarity from Appium. In getting the similarity,
        // we also turn on visualization so we can see what went wrong if something did.
        SimilarityMatchingOptions opts = new SimilarityMatchingOptions();
        opts.withEnabledVisualization();
        File newBaseline = TestFlow.driver.getScreenshotAs(OutputType.FILE);
        MobileElement element = (MobileElement) Helpers.find(locatorType, locator, 3, false);
        BufferedImage newBase=Helpers.generateImage(element, newBaseline);

        SimilarityMatchingResult res = TestFlow.driver.getImagesSimilarity(baselineImg, newBaseline, opts);

        // If the similarity is not high enough, consider the check to have failed
        if (res.getScore() < MATCH_THRESHOLD) 
        {

            File failViz = new File(dir+"/appium_screenshots/"+NameOfClass+"/FAIL_" + NameOfClass + "_" + baseline +"_"+ checkName + ".png");
            try {
                res.storeVisualization(failViz);

            } catch (ClassCastException e) {
                e.printStackTrace();
            }
            TestFlow.lastScreenshotSaveDir=dir+"/appium_screenshots/"+NameOfClass+"/FAIL_" + NameOfClass + "_" +baseline +"_"+ checkName + ".png";

            String abc= String.format("Visual check of '%s' failed; similarity match was only %f, and below the threshold of %f. Visualization written to %s.",
            checkName, res.getScore(), MATCH_THRESHOLD, failViz.getAbsolutePath());
            Assert.fail(abc);

        }

        // Otherwise, it passed!

        sysLogger("debug", String.format("Visual check of '%s' passed; similarity match was %f",checkName, res.getScore()));
        }

Exception Stacktraces

java.lang.ClassCastException: com.google.common.collect.Maps$TransformedEntriesMap cannot be cast to java.lang.String at io.appium.java_client.imagecomparison.ComparisonResult.getVisualization(ComparisonResult.java:63) at io.appium.java_client.imagecomparison.ComparisonResult.storeVisualization(ComparisonResult.java:73) at iOS_ross.helpers.ImageCompare.doVisualCheckByELement(ImageCompare.java:168) at iOS_ross.Promotions_Test.promotion_multiplePictures_zoom(Promotions_Test.java:201) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55) at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55) at org.junit.rules.RunRules.evaluate(RunRules.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:365) at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:272) at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:236) at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:159) at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:386) at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:323) at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:143)

Link To Appium Logs

logs don't give any more informations

mykola-mokhnach commented 3 years ago

There's a known bug in the Appium server code. Try appium@beta or appium@rc instead

RSM-SBA commented 3 years ago

Thanks, do you know if that will be also fixed than in appium 2.0 which will hopefully be released in next weeks ?

mykola-mokhnach commented 3 years ago

In v2.0 this code has been moved to a separate plugin and the recent version of it should have the fix