24
a picture is worth a thousand words David Tolley CI Architect Build/Release

A picture is worth a thousand words David Tolley CI Architect Build/Release

Embed Size (px)

Citation preview

Page 1: A picture is worth a thousand words David Tolley CI Architect Build/Release

a picture is worth a thousand wordsDavid TolleyCI Architect Build/Release

Page 2: A picture is worth a thousand words David Tolley CI Architect Build/Release

A little about meAnd maybe something about Groupon Engineering

Page 2

• Married… sorry for all the… lady… out there

• Contact information:

[email protected]

• Twitter: DavidTolley

• Groupon 400-20,000 engineers

• 300+ commits in a day to main app

• Each commit triggers 9 jobs

• Each job has between several hundred to several thousand tests

• Many other jobs not associated with out primary application

• https://engineering.groupon.com/

• Were always hiring: http://www.groupon.com/techjobs/

Page 3: A picture is worth a thousand words David Tolley CI Architect Build/Release

A Little Selenium TimelineCompletely skewed from only my experiences

Page 3

1. I run tests

2. I get failures

3. Developer says “ Works for me”

4. I print out the stack trace of failures from now on

5. Developer says “Only fails on Jenkins, that stack trace is a red herring”

6. I take a screenshot of the Browser at point of failure, archive it

7. Developer looks at stack trace

8. Developer finds the corresponding screenshot in the build’s artifacts

9. Developer says “This is cool but… I don’t like having to search for a screenshot”

10. I develop a plugin to insert screenshots into test failure details page

11. Developer says “Awesome! Now I easily know what to fix”

Page 4: A picture is worth a thousand words David Tolley CI Architect Build/Release

So what did I learn?Data is awesome

Page 4

But a selenium failure with out visual proof, or a picture without context is hard to digest

Page 5: A picture is worth a thousand words David Tolley CI Architect Build/Release

Words describing a pictureMy “stack trace”

Page 5

• Giant

• Monstrous

• Absurd

• 15 Feet tall by 20 Feet Wide

• Brown stuffed cat crammed into UFO

• Hanging from the celling on 4th floor of Groupon’s Head Quarters

• Giant tongue sticking out of its mouth

• Cat haters worst nightmare

• I feel bad for the person who has to clean it’s litter box

• WTF?!?!

• This has to be a joke…

Page 6: A picture is worth a thousand words David Tolley CI Architect Build/Release

A picture with no contextMy “screenshot”

Page 6

Page 7: A picture is worth a thousand words David Tolley CI Architect Build/Release

When your powers combine…I’m so excited!

Page 7

Pause to build suspense

Page 8: A picture is worth a thousand words David Tolley CI Architect Build/Release

I’m sad to present… Groupon’s MascotMind has been BLOWN

Page 8

• Giant

• Monstrous

• Absurd

• 15 Feet tall by 20 Feet Wide

• Brown stuffed cat crammed into Silver UFO

• Hanging from the celling on 4th floor of Groupon’s Head Quarters

• Giant tongue sticking out of its mouth

• Dog lovers worst nightmare

• I feel bad for the person who has to clean it’s litter box

• WTF?!?!

• This IS real…

Page 9: A picture is worth a thousand words David Tolley CI Architect Build/Release

That’s cool…But how does this fit into Jenkins?

Page 9

TestDataPublisher and TestAction

Along with naming screenshots in accordance with the test that failed

Page 10: A picture is worth a thousand words David Tolley CI Architect Build/Release

TestDataPublisherIf we have failures, try and find a corresponding screenshot

Page 10

if(testObject instanceof CaseResult) {

CaseResult caseResult = (CaseResult)testObject;

String testName = caseResult.getClassName() + "." + caseResult.getName();

String regex = testName.replaceAll(" ", "_");

regex = regex.substring(regex.lastIndexOf(".") + 1, regex.length());

for (Run<?, ? extends AbstractBuild<?, ?>>.Artifact artifact : build.getArtifacts()) {

if(artifact.getFileName().contains(regex)){ //matches(regex)) {

String url = Hudson.getInstance().getRootUrl() + build.getUrl() + "artifact/" + artifact.getHref();

result.add(new ImageBadge(testName, url));

Page 11: A picture is worth a thousand words David Tolley CI Architect Build/Release

TestActionWhen you view a failure, add this action.. Magic is in the Jelly

Page 11

public ImageBadge(String testName, String imageUrl) {

this.testName = testName;

this.imageUrl = imageUrl;

}

<j:jelly xmlns:j="jelly:core">

<style>

img.failure {

cursor: url(${rootURL}/plugin/ImageBadge/zoom.png), auto;

max-height: 190px;

}

</style>

<a href="${it.imageUrl}" target="_blank">

<img class="failure" src="${it.imageUrl}"/>

</a>

</j:jelly>

Page 12: A picture is worth a thousand words David Tolley CI Architect Build/Release

How this looks in JenkinsFailure detail

Page 12

Page 13: A picture is worth a thousand words David Tolley CI Architect Build/Release

Want to see a demo?Of course you do!

Page 13

So show it already…

Page 14: A picture is worth a thousand words David Tolley CI Architect Build/Release

Selenium can take screenshots…And Jenkins can interact with them…

Page 14

Page 15: A picture is worth a thousand words David Tolley CI Architect Build/Release

Screenshot Comparison with Jenkins & SeleniumBest thing since apple pie and ice-cream

Page 15

• Biggest number of bugs in a typical backlog are cosmetic

• Hardest bugs to find are small cosmetic bugs

• Manual testing doesn’t fit well in a lean, fast-paced environment

• Impossible to fully cover UI manually on a Continuous Deployment schedule

Page 16: A picture is worth a thousand words David Tolley CI Architect Build/Release

Screenshot ComparisonSome drawbacks… I mean guidelines.

Page 16

Only ran on release candidates

Need to continually update the “image repo” – so automate this

Need’s to run with the same screen resolution each time it’s ran

Other then that it’s awesome!

Page 17: A picture is worth a thousand words David Tolley CI Architect Build/Release

Screenshot ComparisonStep 1: Auto-magicaly build an image archive

Page 17

Create a selenium “crawler” – capture and store endpoints

1. Selenium already crawls your website, simply add the option to take a screenshot at the end of every test, name it what the test is named

2. SCP to repo (I chose userContent/imageArchive on our master)

Page 18: A picture is worth a thousand words David Tolley CI Architect Build/Release

Screenshot ComparisonStep 2: Create a build that runs on release candidates

Page 18

Create a Jenkins job that can automatically run on your release candidates

1. Much like your crawler job, except tied into your release pipeline

2. Takes the same picture of the same endpoints, and names them the same way

3. Configure ScreenshotComparison plugin, giving it your archive repo to compare against, and location of screenshots on the current run

4. Optionally set a % difference threshold

Page 19: A picture is worth a thousand words David Tolley CI Architect Build/Release

Screenshot ComparisonStep 3: I’ve got the magic in me

Page 19

1. Gets lists of files in the archive repo

2. Gets list of files in current workspace

3. Compares the files with the same name

4. Prints and stores the percent different

Percent Different = Different Pixels / Total pixels

Page 20: A picture is worth a thousand words David Tolley CI Architect Build/Release

Screenshot ComparisonStep 4: Slightly different images.

Page 20

Page 21: A picture is worth a thousand words David Tolley CI Architect Build/Release

Screenshot ComparisonStep 5: All this for a little console output

Page 21

Page 22: A picture is worth a thousand words David Tolley CI Architect Build/Release

Screenshot ComparisonWhat’s really compared?

Page 22

1. Colors

2. Positioning

3. Text

4. Sizes

5. EVERYTHING – every pixel is compared to each other

Page 23: A picture is worth a thousand words David Tolley CI Architect Build/Release

Last but not leastTolleyvision

Page 23

Page 24: A picture is worth a thousand words David Tolley CI Architect Build/Release

Thank You To Our Sponsors