Zach Attas

.01
About Me
.02
Selenium Fun
.03
Experience
.04
Speaking
.05
Skills
.06
Projects
.07
Contact

About Me


Hey, I'm Zach. I majored in philosophy in college, so I've always enjoyed questioning things.  After college, I took a job as a Quality Assurance analyst, not really knowing what Quality Assurance was, but knowing that I would be working for an exciting, cool software company, Epic!

Once I learned about testing, on the job, I discovered that I liked it a lot! It appealed to the same part of my brain that was interested in philosophy. In pursuit of more testing expertise, I began digging 'under the hood' by teaching myself programming -- and soon I was hooked, scriping setup and contributing unit tests at Epic. Then I decided to do a Udacity bootcamp, to teach myself modern programming.

Now I'm a Software Development Engineer in Test (SDET), and haven't looked back since. I currently work at Capsule as a Staff SDET.

I love digging into problems. I'm self-taught, so my programming education comes from a random assortment of MOOCs (Massive Open Online Courses), textbooks, podcasts, blogposts, stack overflow articles, meetup.com events, and small projects. When I'm not learning, I'm taking photography classes, improv classes, cooking something yummy, or managing the Chicago Seleniumistas Meetup Group.

Selenium Fun

Selenium Fun

Run this Selenium script on your computer to get a fun message!


To install packages:
gem install selenium-webdriver
gem install webdrivers

To run the Selenium script:
require "selenium-webdriver"
require "webdrivers"

driver = Selenium::WebDriver.for :firefox # for firefox
# driver = Selenium::WebDriver.for :chrome # for chrome

driver.navigate.to "https://www.zattas.me"
cookie = { name: "name", value: `whoami`.chomp }
driver.manage.add_cookie(cookie)
driver.manage.window.maximize

sleep 1000 # Take your time and enjoy the site!

driver.quit

To install packages:
pip install selenium
# Export a driver executable into your PATH variable
# Executables:
#    firefox - https://github.com/mozilla/geckodriver/releases
#    chrome - https://chromedriver.storage.googleapis.com/index.html
# Let's say you put your executable file in your $HOME/drivers directory
#    Then to make it useable by the below script, you would run this to
#    put the directory into your path:
export PATH=$HOME/drivers:$PATH

To run the Selenium script:
from selenium import webdriver
import getpass
import time

driver = webdriver.Firefox() # for firefox
# driver = webdriver.Chrome() # for chrome

driver.get("https://www.zattas.me")
cookie = { "name": "name", "value": getpass.getuser() }
driver.add_cookie(cookie)
driver.maximize_window()
time.sleep(1000) # Take your time and enjoy the site!

driver.close()

To install packages:
npm init && npm install --save-dev selenium-webdriver
# Export a driver executable into your PATH variable
# Executables:
#    firefox - https://github.com/mozilla/geckodriver/releases
#    chrome - https://chromedriver.storage.googleapis.com/index.html
# Let's say you put your executable file in your $HOME/drivers directory
#    Then to make it useable by the below script, you would run this to
#    put the directory into your path:
export PATH=$HOME/drivers:$PATH

To run the Selenium script:
const webdriver = require("selenium-webdriver");
const os = require("os");

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

let driver = new webdriver.Builder().forBrowser("firefox").build(); // for firefox
//let driver = new webdriver.Builder().forBrowser("chrome").build(); // for chrome

(async function example() {
  try {
    await driver.get("https://www.zattas.me");
    var cookie = { "name": "name", "value": os.userInfo().username };
    await driver.manage().addCookie(cookie);
    await driver.manage().window().maximize();
    await sleep(1000000); // Take your time and enjoy the site!
  } finally {
    await driver.quit();
  }
})()

Experience

Capsule

Capsule


Staff SDET Jan '22 - now
New York, NY (but working remotely)

Developing Capsule's first widely used integration and end-to-end tests

Piloting Capsule's Acceptance Testing process for QA team members

Created a microservice for use in integration tests to introspect on messages sent over SNS (Amazon tech)

ReviewTrackers

ReviewTrackers


Lead SDET Feb '20 - Nov '21'
Senior SDET March '18 - Feb '20
Chicago, IL

Shaved end-to-end suite runtime from 30+ mins down to 5 mins in CI and 10 mins in CD

Cultivate engineering culture so anyone can contribute to end-to-end tests

Develop mock servers to test 3rd party api integrations

Rolled a custom integration with Report Portal to monitor suite health over time

Manage a team of 3

Jellyvision

Jellyvision


SDET
Chicago, IL
Mar '17 - Mar '18

Created end-to-end analytics tests with proxying

Developed new infrastructure to run browser tests in continuous integration pipelines

Reduced runtime of all automated tests by >50% through engineering practices and implicit waits

Chef

Robinia Courtyard


Prep Chef
Madison, WI
Oct '15 - Aug '16

Organized walk-in

Ground meat, daily

Cooked all house stocks

Prepped ingredients and recipes for a 35+ item menu

Completed Intro to Programming and Full Stack Nanodegrees while being a chef

Epic Systems

Epic


Quality Assurance
Madison, WI
Aug '13 - Oct '15

Wrote unit tests for core backend APIs and internationalization tools

Developed one-off testing tools, .e.g., a script to grade internal projects

Managed error investigation and disclosure for serious low-level technical issues

Speaking

appium conference sept 2021

Appium Conference


September 2021

What else can we automate? How to extend your skills and constantly be learning

rabbitmq summit July 2021

RabbitMQ Summit


July 2021

Take The Path Of Least Resistance For Your Test Data

rabbitmq summit Nov 2020

Testing United


Nov 2020

Setting Yourself Up For Success So Anyone Can Understand And Write Tests

seleniumconf india 2020

SeleniumConf India


June 2020

Selenium For All - Setting Your Team Up For Success So Anyone Can Understand and Write Tests

This talk was also presented at the Continuous Testing Meetup based out of Berlin

quest for quality

Quest For Quality


Nov 2019

Services: How to Test Them When You Have The Keys to The Castle

seleniumconf india 2018

AgileTestingDays Chicago


May 2019

Flaky test or actual issue? You decide

seleniumconf india 2018

SeleniumConf India


June 2018

How to Un-Flake Flaky Tests- a New Hire's Toolkit

podcast

The Ruby Testing Podcast


by Jason Swett

Jason and I talk about QA, Selenium, SitePrism and a number of other things

Skills

Testing topics that I am passionate about:

Test Reporting
  • Test reports should look as nice as possible. Spend time making them easy to read.

  • Test errors should have clear next steps and clear error messages for what systems to investigate.

  • A failed test should report the username/password/account_id used in that test, for easy troubleshooting.

  • All test outcomes should be reported somewhere to be analyzed for flakiness and other test trends over time.

  • Any file that a test generates and has assertions against, save to a s3 bucket somewhere at the end of the run.
    • That way, if an issue occurs with any test associated with one of these files, one can see the file and see what went wrong without having to rerun the test.

    Test Architecture
  • Sign the data created by your test factories. This means - attach a piece of metadata to the account row created by the test, so that, all data associated with this account can be known as ‘test data' and treated as such. When done this way:
    • Data cleanup can occur at the end of the day (not at the end of the test), since one can easily query and retrieve all data created by tests in an environment. This saves time!
    • If you want to mock something in the software under test, you can have it check if the data is signed or not, and mock based on that. This way, normal accounts in lower environment are not mocked, and test accounts are mocked.
  • Write a cookie to the browser, which the frontend can use to mock things that make sense to be mocked on the frontend. When done this way:
    • You could mock the google autocomplete api, so test environments do not expend google credits, and you could still test google's implementation in the frontend through your mock in the cookie.
    • You could make toast messages not timeout, for easier selenium testing (nothing's worse than having selenium try to find a timed-out toast message).
  • Have robust and clever ways to wait for asynchronous tasks, which include:
    • Querying the DB directly.
    • Looking for things on the frontend and reloading the page to do so.
    • Querying existing APIs.
    • Writing testing APIs in the software under test.
  • For any test that depends on a microservice, in some kind of before hook, have that test ping its /status endpoint, and fail if it doesn't 200.
    • That way the test fails right there, and you know where to look to fix it.
    • Also, the test would have failed later on with a possibly more cryptic fail (depending on how the service not being up is handled in the software under test). No need to expend mental energy on that!
  • Log in via an api and inject the token into your browser session. That way, you don't have to log in via a frontend form
    • You should still have ONE manual log in test though!

    Cool testing features I've worked on in my career:

    Technologies
  • Load test with Locust.

  • Cross browser tests with Sauce Labs and BrowserStack.

  • Visual Regression testing with Percy.

  • Setting up a Selenium Grid with Selenoid (Selenium Grid, but in Golang).

  • Proxying all requests in a Selenium Grid test run (generating 200mb data per run) and dumping that into a csv for analysis using BrowserMob Proxy and Puffing Billy.

  • Test Reporting with ReportPortal and RspecHtmlReporter (with custom code to work in parallel and with the rspec-retry gem and parallel_tests gem).

  • Maintain a small mobile app test suite with appium in AWS DeviceFarm.


  • Implemented Features
  • Implemented a Sinatra mock server to share a contract between the software under test and the test itself for testing certain critical business functions.

  • Implemented the ability to run a specific test in CI (as opposed to the whole suite).

  • Setting up a Selenium Grid with Selenoid (Selenium Grid, but in Golang).

  • Implemented a healthcheck process which runs the whole suite of tests 10 times back to back, overnight, in CI ephemeral environments, to get an accurate picture of test health on the main branches.

  • Tests normally run in 50 parallel processes, chunked by their average runtimes, for even process distribution and the fastest runtime possible. But I implemented a feature to randomize the test groups and tests within those groups (by a recorded seed) so that we can weed out unintended cross-pollination between tests. This randomized run happens once daily to find these kinds of fails and manage the overall health of the suite.

  • Created a testing logger that logs out all crucial steps of a Selenium test (booting up a browser, running an async task, visiting a new page). It is useful to have all of those log messages with timestamps for debugging the software under test. This logger also logs the javascript console messages the browser received during the test (these are often just extra noise, but sometimes, useful!)

  • Created a rabbitmq server consumer process specifically for setting up data for end-to-end tests, in the software-under-test.
  • Projects

    Flights140

    Flights140 (no longer live)


    Created Nov '16

    Website that uses Twitter to find airfare deals and alerts users (via email and/or text)

    Technologies Used:

    Python

    Javascript

    Django

    Jinja2

    Celery

    RabbitMQ

    PostgreSQL

    Python Social Auth

    Google Places API

    AJAX

    Supervisor

    Regex

    SendGrid

    Twilio

    Heroku

    Semantic UI

    Bootstrap

    Animate.css

    Shut The Box

    Shut The Box


    Created Nov '16

    Website implementation of the British dice rolling game Shut The Box

    Technologies Used:

    Node.js

    Express

    Promise.js

    Webpack

    jQuery

    Underscore.js


    Semantic UI

    Animate.css

    pug

    Python

    Google Cloud Endpoints

    Heroku

    LizardApp

    Obey The Testing Goat


    Created Nov '16

    Went through this amazing book, chapter by chapter

    Created a website using TDD with 100% test coverage

    Technologies Used:

    Python

    Django

    Gunicorn

    Selenium

    Fabric

    Digital Ocean

    Jenkins

    LizardApp

    Lizard Mgmt Tool


    Created Sept '16

    Add, edit, and delete lizards and lizard's hobbies

    Accepts login from Google and/or Facebook

    Logs all recent activity on the homepage

    Technologies Used:

    Python

    Flask

    SQLAlchemy

    PostgreSQL

    Jinja2

    Bootstrap

    Heroku

    LizardApp

    Note-Taker


    Created April '16

    Final project for Udacity's Intro to Programming Nanodegree

    Note-taking app with heirarchy of note types

    Responsive design

    Technologies Used:

    Python

    jQuery

    Bootstrap

    Google App Engine

    Contact

    Created with by Zach Attas • View on github • Deployed on a DigitalOcean Droplet