Compare Images In Android Automation Testing

Foreword

This article was posted by me original on our company internal WIKI, now i shared here since i think may be it is useful to others.


Many projects are about photo displays in our group. So a touch problem must be met during we doing automation that "how to compare two images in automation testing?" 

Here i try to give a solution about it on android platform.

we know that android developers usually use ImageView to show a photo on activity, and if necessary, they will also modify or re-size the photo before shown. Following is a example code snipping that we maybe see it in usual work:

private ImageView imgView;
 
imgView = (ImageView) findViewById(R.id.imageViewId);
 
imgView.setImageResource(R.drawable.imageFileId);

Or

private ImageView imgView;
 
imgView = (ImageView) findViewById(R.id.imageViewId);
 
imgView.setImageBitmap(BitmapFactory.decodeFile("pathToImageFile"));

So in order to compare the images, firstly we need get the image from ImageView:

public Bitmap getBitmap(int id)
 
{
    ImageView img =  (ImageView)solo.getView(id);
 
    BitmapDrawable draw = (BitmapDrawable) img.getDrawable();
 
    return draw.getBitmap();
}

Please note although it is not the same object that the developers set, but it is the one that we (namely users) actually see, so we use this bitmap as the baseline in automation testing is totally proper to cover manual test case.
Then second, we can compare the two target bitmap via pixel to pixel:

/**
     * Compare two photos by pixel to pixel, and if the compared result is not as expected
     * This method will save the two bitmaps as PNG file under /mnt/sdcard/moonriseTest/BitmapCaptures/
     * @param bm1 bitmap will be compared with bm2
     * @param bm2 bitmap will compared with bm1
     * @param expected what you expected result for whether these two photos are same or not
     * @return true if these two images are same, otherwise return false
     */
    public static boolean compareImages(Bitmap bm1, Bitmap bm2, boolean expected)
    {
        boolean result = true;
        //if(bm1.getHeight() != bm2.getHeight() ) result = false;
        //if(bm1.getWidth() != bm2.getWidth()) result = false;
 
        outerLoop:
        for(int x =0; x < bm1.getWidth(); x++)
            for(int y = 0; y < bm1.getHeight(); y++)
                if(bm1.getPixel(x, y) != bm2.getPixel(x, y)){
                    result = false;
                    break outerLoop;
                }
 
        if(expected != result)
        {
            Log.i(Global.TAG, "Not expected, here save these two bitmap as PNG");
            FileManager.saveAsPNGFile(bm1, "bm1");
            FileManager.saveAsPNGFile(bm2, "bm2");
        }
 
        return result;
 
    }

Please note, the code above are copied from our test project. You can see that we also add a helper function that if the compared result is not as expected, we will save these two bitmaps as PNG photos, so that we can check why these photos are different easily.

/**
     * Save the bitmap as PNG file under /mnt/sdcard/YourExpectedPath
     * 
     * @param bm bitmap that you want to save
     * @param fileNameExtension a tag for the png file name
     */
    public static void saveAsPNGFile(Bitmap bm, String fileNameExtension){
        String path = Environment.getExternalStorageDirectory().getPath()
                + "/YourExpectedPath/";
        String filename;
        try {
            Date date = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmms");
            filename = sdf.format(date);
            File dic = new File(path);
            if(!dic.exists())
                dic.mkdirs();
            File file = new File(path, filename +"_"+fileNameExtension + ".PNG");
            FileOutputStream out = new FileOutputStream(file);
            bm.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            Log.e(Global.TAG + "Save bitmap file failed", ex.getMessage());
        }
    }

BTW, in practical work you may also meet the scenarios that some bitmap objects were already recycled before you start to compare. In these situations, we can save the bitmap to pixels arrays when it is active and then compare the pixels array in the future!

Conclusion

Actually, in my opinion, nothings was complex, the only thing that we need to do is to find the question, then go to resolve it, and during the process, you will gain more!

posted @ 2013-04-24 15:15  大卡尔  阅读(2250)  评论(0编辑  收藏  举报