4

Basically what I have is a list of items and i can create a new item in that list using a button.

Now I want to test whether the item is added in the list when button is clicked or not.

While creating a test case for this, i thought of taking screenshots before and after tapping button and comparing them to know if item is added. But now i am stuck as how to compare two screenshots.

PS: List is complex and items may contain different data.

private func takeScreenshot() -> XCUIScreenshot{
    return XCUIScreen.main.screenshot()
}


private func testElements(){
    let app = XCUIApplication()
    app.buttons["List Items"].tap()
    app.tables["OuterTable"].cells.allElementsBoundByIndex.first?.tap()
    let createBar = app.otherElements["createBar"]
    let button = app.buttons["CreateButton"]
    let initialScreenshot = takeScreenshot()
    button.tap()
    let newScreenshot = takeScreenshot()
    //Compare initialScreenshot and new Screenshot
}

PS: List is displayed in bottom up manner just like you see chats new items would be added at bottom.

Shivam Pokhriyal
  • 479
  • 4
  • 14
  • Can you please add what you have already tried? – regina_fallangi Aug 29 '18 at 14:23
  • I haven't actually, as you can see in the question i am stuck as how to compare two screenshots. Nonetheless, i will add the code for reference – Shivam Pokhriyal Aug 29 '18 at 14:32
  • @regina_fallangi Added code please check if you need anything else – Shivam Pokhriyal Aug 29 '18 at 14:39
  • An image is effectively an NxM matrix containing tuples of (R,G,B,A) values. The naíve approach would be to subtract the two image matrices along each channel, and then summing that subtraction. If the sum for all channels is 0 or within some tolerance value, the two screenshots are identical. – Daniel R. Livingston Aug 29 '18 at 14:44
  • Is there any other way it seems too time consuming. Or any other way to detect if new item is added in the list – Shivam Pokhriyal Aug 29 '18 at 14:46
  • Effectively, what you should be doing is something like this (psuedo-code - not Swift!!): `old = list.getListContents(); button.tap(); new = list.getListConents(); if old.length < new.length { return TEST_PASSED } else { return TEST_FAILED }` – Daniel R. Livingston Aug 29 '18 at 14:50
  • Apple has an API for testing with screenshots: https://developer.apple.com/documentation/xctest/xcuiscreenshot – dr_barto Aug 29 '18 at 14:50
  • @dr_barto I already followed that link and it has no method to compare two screenshots, please see the question. – Shivam Pokhriyal Aug 29 '18 at 14:59
  • `XCUIScreenshot` conforms to `Equatable`, so have you tried to just compare two screenshot instances? – dr_barto Aug 29 '18 at 15:09
  • @dr_barto equatable checks for object hash code or something related to that. It doesn't check whether the two images are identical. – Shivam Pokhriyal Aug 29 '18 at 15:17
  • How `Equatable` checks the equality is an implementation detail, it could do what you assume or actually compare the underlaying pixel data. I'd give it a try. – dr_barto Aug 29 '18 at 15:55

2 Answers2

2

There is a library called iOSSnapshotTestCase(FBSnapshotTestCase) that does just this. Once a Facebook project, now an Uber project.

iOSSnapshotTestCase

It is setup to take screenshots of your views/view controllers and then on subsequent test runs, it will compare your views with the saved snapshot image, and produce an output image showing any differences.

I've read from https://www.objc.io/issues/15-testing/snapshot-testing/ that:

"It makes the comparison by drawing both the view or layer and the existing snapshot into two CGContextRefs and doing a memory comparison of them with the C function memcmp()."

bandejapaisa
  • 26,576
  • 13
  • 94
  • 112
  • Theres also a library called SnapshotTesting (written in Swift) that works great: https://github.com/pointfreeco/swift-snapshot-testing – Jochen Holzer Oct 06 '22 at 12:29
0

You can compare the raw data of the screenshot images using the pngRepresentation property:

let expectedResult = initialScreenshot.pngRepresentation == newScreenshot.pngRepresentation

XCTAssert(expectedResult, "the screenshots don't match")
Jochen Holzer
  • 1,598
  • 19
  • 25