fun

PyOhio 2018 Reflections

PyOhio 2018 was a free Python conference hosted at Ohio State University in Columbus, OH from July 28-29. I had the pleasure of not only attending but also speaking at PyOhio, and my company, PrecisionLender, graciously covered my travel expenses. I had a great time. Here’s my retrospective on the conference.

My Talk

The main reason I went to PyOhio was because I was honored to be a speaker. When I was at an Instagram dinner at PyCon 2018, I met a few conference organizers who encouraged me to propose talks at other Python conferences. On a whim the next morning, I spitballed an idea for a talk about building a test automation solution from the ground up in Python. After talking with a number of people, I realized how test automation is such a struggle everywhere. I took inspiration from Ying Li’s keynote and crafted a story about how Amanda the Panda, a Bamboozle employee, becomes a test automation champion. And, BOOM! My talk proposal was accepted for PyOhio and PyGotham! The video recording for my talk, “Egad! How Do We Start Writing (Better) Tests?”, is below:

Arrival

Good news: Raleigh and Columbus have direct flights. Bad news: they are either early-morning or late-night direct flights. So, I left Raleigh on Friday morning before the conference and spent the day in Columbus. Surprisingly, the security line at RDU wrapped around 2/3 of the Terminal 2 perimeter, but I still boarded the flight on time. Once I landed in Columbus, I took the COTA AirConnect bus downtown for the low price of $2.75.

My goal for Friday was personal development. I rarely get a chance to escape the rigors of everyday life to focus on myself. Personal retreats let me clear my mind, dream big, and begin taking action. And on this day, I started writing my first test automation book – a dream I’ve held for over a year now. I spent a few hours at Wolf’s Ridge Brewery, sampling beers with lunch as I developed a rough outline for my project.

My evening was low-key. I took a nap at my hotel, the Blackwell Inn and Pfahl Conference Center. For dinner, I ate at White Castle for the first time – and it was pretty darn good. After practicing my talk, I got a tiramisu bubble tea from Vivi as a night cap.

The Conference

PyOhio was a much smaller conference than PyCon. There were fewer vendor tables but nevertheless a wide selection of stellar talks. As a result, the conference felt more intimate and more focused. Perhaps that feeling was due also to the venue: the third floor of the Ohio Union had full rooms with “cozy” hallways. Hats off to the organizers, too – everything ran smoothly and professionally.

As soon as I arrived, I scored my name badge, my swag bag, and my official PyOhio 2018 t-shirt. The opening keynote from Adrienne Lowe, “From Support to Engineering and Beyond: What to Take with You, and What to Leave Behind,” about the highs and lows of trying to make it as a developer was exceptionally inspiring. Engineers often don’t talk about how hard the job is, especially for newcomers to the industry. Everybody suffers from imposter syndrome. Everybody feels inadequate. Everybody is tempted to quit, even to the point of tears. The vulnerability in hearing others say, “Me, too,” is so relatable and so relieving.

The first talk-talk I attended was Trey Hunner’s “Easier Classes: Python Classes Without All the Cruft.” Trey gave an excellent overview of writing more sophisticated Python classes. TL;DR: upgrade to 3.7 and use dataclasses.

The next talk I attended was Leo Guinan’s “Go with the Flow: Automating Your Workflows with Airflow.” Apache Airflow is a platform for automating workflows. As an automationeer, it struck me as being like a continuous integration system generalized for non-build purposes. The Q&A portion of the talk was lit.

After finding an authentic Chinese restaurant for lunch, my friend Matt arrived! I worked with Matt in the testing space at LexisNexis. He drove all the way from Dayton to see my talk and hang out. We spent the early afternoon catching up, and we went to Hook Hearted Brewing for dinner after the conference because we’re beer buddies. I was so thankful he came to support me – it meant a lot!

My talk was at 3:45pm. Other than discovering my Thunderbolt-to-HDMI adapter was a dud, the talk went very well. I decided to stick to a script for this talk because most of it followed a story, and I’m glad I did. (For my PyCon talk, I chose instead to speak without a script and rely instead on the slides alone.) There were about 30 people in the audience. Many expressed appreciation for my presentation!

The last talk of the day for me was Jace Browning’s “Automated Regression Testing with Splinter and Jupyter.” It was the perfect follow-up to my talk. Whereas mine was mostly high-level, Jace showed implementation and execution. I loved how he compared raw Selenium WebDriver calls to splinter calls, and I was thrilled to see hands-on test execution using Jupyter. One of the things that makes Python so great for automation is that modules can be called from the interpreter – and Jupyter notebooks make that so easy.

The Second Day

Sunday was a shorter conference day. The opening keynote, Lorena Mesa’s “Now is better than Never: What the Zen of Python can teach us about Data Ethics,” didn’t start until 11:40am. Lorena showed us what the Zen of Python can teach us about data ethics in a scary, modern world.

I got lunch at Chatime: dan dan noodles (or rather, an imitation thereof) and a matcha latte with grass jelly. Yum! After lunch, I attended Daniel Lindeman’s “Python in Serverless Architectures.” Now I know what the buzzword “serverless” means! I even found out that I had already developed a serverless app using Django and Heroku. There are some really cool ways test automation could take advantage of serverless architectures.

Another one of my favorite talks of the afternoon was Vince Salvino’s “Containers Without the Magic.” Vince broke down how easy containers are to use. It was a great refresher for me.

Open Spaces

At 3:15 on Sunday, I tried something new: I hosted an open space for test automation. “Open spaces” are rooms that can be reserved for a time slot to meet up informally about a common interest. (For example, PyCon had a juggling open space!) At first, nobody showed up to my open space, but after a few minutes, one lady walked in. She had been a software tester for years and wanted to start doing automation. I walked her through as much info as I could before time was up. She was very grateful for the guidance I offered. It worked out nicely that she was the only person to come to my open space so that she could really get value out of it. (My friend Jason also popped in and helped out; more on him below.)

The After-Party

At conferences, my biggest fear is being awkwardly alone. I want to spend time with good people, both new and familiar. Thankfully, PyOhio didn’t disappoint.

Backstory: At PyCon 2018, I met a guy named Julian who runs PyBites (together with his buddy Bob). We really hit it off, and he invited me to join the PyBites community. They offer great code challenges and a “100 Days of Code” challenge course, as well as a blog about all things Python. Through the PyBites community, I met another guy named Jason who would be at PyOhio 2018 with me. We agreed to meet up for dinner and drinks after the Sunday talks.

(On a side note, I recommend PyBites as a great place to learn new things, hone skills, and meet great people!)

That Sunday night, it just so happened that Adrienne and Trey, two of the other speakers, intersected Jason and me as we were deciding where to go for dinner. The next thing we know (after a hotel pitstop), we’re all walking off together to Eden Burger, a local vegan burger joint. I had a vegan “cheeseburger” with fries and a “milkshake” – and they were genuinely delicious! More than the food, I enjoyed my time with new friends. I was really inspired by the cool things each of them is doing. I guess that’s Python conference magic!

Jason and I hit World of Beer after dinner. After Slack-ing for weeks, it was so good to spend time with this fine gent. We discussed Python, software, our careers, our families, and our dreams. What a perfect way to conclude PyOhio 2018!

Takeaways

There were so many takeaways from PyOhio 2018 for me:

  1. Conferences are phenomenal for professional development. The pulse I get from conferences is electrifying. I walked away from PyOhio galvanized to be an even better software engineer. The talks opened up exciting new ideas. Inspiration for several blog posts sprang forward. The people I met motivated me to try new things. I got so much vigor out of such a short time.
  2. My friends around the globe are awesome. Matt, Jason, Adrienne, Trey, Julian (vicariously), and all the other great people I met at PyOhio made my conference experience so rewarding.
  3. Good values foster wonderful communities. My company, PrecisionLender, has four major values: Be helpful, humble, honest, and human. Those values make my company such a great place to work. I see those same values in the Python community, too. People at PyOhio even asked about these values when they saw them on my PL shirt and my business card. I think that’s partially why Python conferences are always so welcoming and inspiring.
  4. Bigger conferences have more pizzazz, while smaller conferences are more intimate. PyCon 2018 was big, flashy, and awesome. I scored so much swag that I nearly couldn’t fit it all in my suitcase to carry home. PyOhio 2018, on the other hand, focused much more intently on the talks and the people. A perfect example of this was Leo Guinan’s monologue-turned-dialogue on Airflow: it was natural for people to just ask questions. Both types of conferences are good in their own ways.
  5. PyCon 2018 was likely a watershed moment for my career. I cannot reflect on PyOhio 2018 without seeing it as an extension of my PyCon 2018 experience. The only reason I attended PyOhio was because someone at PyCon encouraged me to propose a talk. The reason I met Jason is because I first met Julian. The reason I want to keep speaking is because PyCon went so well for me. The fact that both conferences were hosted in Ohio only two months apart is also rather serendipitous. Like my first trip to China, I think PyCon 2018 will have a lasting impact on my career.

A Cucumber Kimchi Recipe

My wife and I love to eat kimchi. Recently, I started making it at home instead of buying the big (expensive) jars at our local Asian market. I just made oi-sobagi (오이소박이), a cucumber kimchi, for the first time. Given that “Cucumber” is a test automation buzzword, I figured I’d share the recipe here. I hope you enjoy it as much as my Chinese cucumber recipe!

The recipe I used came from Maangchi, “YouTube’s Korean Julia Child.” She has many other delicious Korean recipes, too. Her oi-sobagi recipe is here:

A Panda’s Retrospective on The Legend of Zelda: Breath of the Wild

Warning #1: This post has nothing to do with software development or testing. It is purely a post for my own pleasure.

Warning #2: SPOILER ALERT! This post is full of ’em.

The Legend of Zelda: Breath of the Wild is one of my favorite video games. Ever. I’ve been playing it regularly on my Wii U since Christmas, and I just beat the main quest. I redeemed all four Divine Beasts, found all 120 shrines, recovered all memories, and got a majority of the Korok seeds and Hyrule Compendium. It was truly the (virtual) adventure of a lifetime! In celebration of finally beating the game, I’m going to retrospect on what I loved about it so much.

What’s It About?

If you don’t know what this game is about, watch this:

Here’s the story: You, as a young man named Link, wake up in a cave with no memory about yourself or your past. As you explore the world and recover your memories, you discover that the kingdom of Hyrule was destroyed 100 years ago by the evil Calamity Ganon. Princess Zelda has sealed Ganon inside Hyrule Castle since then, but her power is weakening. You, along with four other “champions,” fought together to defeat Ganon but failed, and you yourself were nearly killed. Your main mission is to explore the land to strengthening yourself, recover lost memories, and reawaken four divine beasts. Then, you need to storm the castle to defeat Ganon, rescue Zelda, and bring a lasting peace to Hyrule.

How I Played

When BOTW was first announced as an open-world adventure, I immediately shut out all news and reviews aside from official trailers. I adamantly did not want any spoilers whatsoever. I wanted to fully explore the game on my own. And, truth be told, it was totally worth it.

When I play video games, I tend to be a completionist. I like to leave no stone unturned, and I take time to power up as much as possible before big challenges. As a result, my progress rate in BOTW was rather slow, but I feel like I didn’t miss out on anything. Even then, there are still side quests left incomplete and Korok seeds left unfound. All told, I spent 241 hours on a single save file.

botw_playtime

My total playtime after defeating Ganon.

After completing the Great Plateau and fully restoring the Sheikah Slate, my main approach to exploration was to look for shrines in a new area using the binoculars, make a mad rush for the shrine to claim a safety post, and then thoroughly search the surrounding areas for new stuff. I literally went around blind because I didn’t know where to find the Divine Beasts. Here’s roughly the path I took:

  1. Scoured Necluda for shrines for a while.
  2. Went to Zora’s Domain and reclaimed Vah Ruta.
  3. Went to the Great Hyrule Forest but couldn’t take the Master Sword.
  4. Found the Ancient Tech Lab in Akkala.
  5. Criss-crossed Hyrule Field and got blown up by Guardians.
  6. Climbed Mount Lanayru and OH CRAP THERE’S A DRAGON!
  7. Cross-dressed my way through the Gerudo Desert and reclaimed Vah Nabooris.
  8. Froze my butt off in the Gerudo Highlands.
  9. Rode through Lake Hylia and Faron.
  10. Took wings in Tabantha and reclaimed Vah Medoh.
  11. Set my butt on fire on Death Mountain and reclaimed Vah Rudania.
  12. Decided to freeze my butt off again, but this time in Hebra.
  13. Stormed Hyrule Castle, kicking butt and taking names.

For combat, I really preferred nimble melee combat. I favored single-handed weapons and spears. I got pretty good with arrows, too, and I would often try to sneak around as an archer before wailing on enemies with a sword.

guardian_artwork

Guardians – ruining Link’s day, every day.

I did not purchase the DLC, and I probably won’t anytime soon. Why? I simply don’t have time. I didn’t feel like the game was lacking without the DLC, though it looks like it adds some cool content.

What I Loved

The open world was breathtaking. The scenery was truly beautiful, and the whole game was completely explorable. Except for the very edges of the map, there were no invisible walls: if it was there, you could climb it or jump it.

https3a2f2fblueprint-api-production-s3-amazonaws-com2fuploads2fcard2fimage2f6711412fcfc041c6-cef4-4b89-8745-b3cf1d7a8570

It’s just wild.

As the player, you chose the order of events. In other Zelda games, as in most adventure games, the main quest is completely linear. The player must complete events in a certain order to progress. However, in BOTW, after fully restoring the Sheikah Slate, you can make up your own adventure. The divine beasts are recommended but not required. You can even attempt to fight Ganon immediately after stepping off the Great Plateau (though the King’s ghost rightfully says that would be foolish). If I were to play it again, I’d probably do this order: Necluda/Faron, Great Hyrule Forest, Zora’s Domain, Death Mountain, Tabantha, and Gerudo Desert.

The non-linear unfolding of memories made the story so much more engaging. Until you beat the main quest, you really don’t know everything that happened in the past. You find out bits and pieces about Link, Zelda, and the Champions all throughout the quest. The flashbacks become wonderful rewards for progression.

The Sheikah. My favorite race in BOTW are the Sheikah. They are bona fide ninjas with Jōmon stylistics. They’re the underdog good guys who help Link. They made the greatest technology in Hyrule. And for once, the Sheikah are a living, thriving people group. I loved running around Hyrule wearing the Sheikah armor in honor of the Sheikah.

tumblr_oq01gwfwmp1qhgj2mo1_500

I want a man bun like that.

The Gorons are hilarious. If the Sheikah are my #1, then the Gorons are my #2. They’re very friendly people with priceless facial expressions.

This slideshow requires JavaScript.

The music was elegantly serene. It always perfectly complemented the location. From the piano taps while crossing the fields on horseback, to the rambunctious trombones of Goron City, to the violins of Hateno Village that could move you to tears, the music was on point.

Sheikah technology is so cool. Link is running around Hyrule with a mobile phone. The only thing it can’t do is make phone calls!

sheikah-slate-breath-of-the-wild

So, somehow, Hyrule regressed after 10,000 years?

Cooking. I love cooking. The fact that it’s in a Zelda game is incredible. ‘Nuff said.

5c06dba4cd3432d490d919c0895ff0e4

Iron Chef Link!

Favorite Moments

Meeting the Sheikah monk at the end of every shrine. I loved how each monk had a unique name and pose. I also loved how the blue light would shatter as the monk blessed you with the Spirit Orb.

026

Every time was a special encounter.

The first horse. Taming, riding, and domesticating my first horse blew my mind. (Remember, I had no spoilers, not even horses.) I still have my first horse, a brown one with a white butt who I named Buttercup.

buttercup.jpg

Look at mah horse – mah horse is amazing!

The first Lynel defeat. I felt UNSTOPPABLE.

ee9

This is not easy.

The first blood moon. I panicked because I had no idea what was happening.

Discovering the Great Skeleton in Hebra. It’s in a secret, beautiful cavern under a mountain peak.

Defeating Master Kohga. I delighted in sending him straight down to hell where he belonged. I had zero tolerance for the Yiga Clan.

Finding Gorons in Gerudo Town. They don’t even know how they got it!

gtxdtk9zj7ny

It must be the gems.

Building Tarrey Town. Tarrey town is the place where all the races come together to build a productive new settlement together in peace. Everyone gets along. You can find some of the best goods in Hyrule there. It’s also the antithesis of the Great Calamity’s destruction: rather than finding previous towns decimated into ruins, Tarrey Town is the face of the new Hyrule rising from the ashes.

Finding the Hylian Shield. From the beginning, I hoped that the Hylian shield would be available somewhere in the game. I didn’t find it until the end of the game, but when I did, the shield was righteous.

Zelda’s face at the end of the game. #worthit

a87b59737f442d9c36c5eea72d68f923984f6f79_00

How is she 117 years old?

Finding out the location of Paya’s birthmark. Paya is probably my favorite character in the game. She’s a sweet, innocent Sheikah lass with a monster crush on Link. She will tell you she got her name from a papaya-seed-shaped birthmark somewhere on her body, but she won’t say where. I spent the whole game wondering where that birthmark was. Forget defeating Ganon and saving the princess, I just wanted to know. After finally completing the heirloom shrine in Kakariko Village (which was my last shrine because I overlooked the diary), Impa finally tells you.

5ynciqb

And now we know.

Some Critique

Although BOTW is marvelous, there were a few things I felt could have been improved. These critiques do not in any way mean that the game was poor.

It rains too much in Hyrule. Wanna go climbing? Nope – it’s a slip ‘n slide. Need to cook some food on-the-go? Sorry – flame goes out. Stuck waiting for time to pass? No sitting by a fire. Trying to explode a powder keg on some Bokoblins? Not today. And let’s just hurl some lighting bolts at you while you cross an open field, too. The rain does nothing but block your progress. My biggest frustration was climbing: I couldn’t explore the areas I wanted to go, and I couldn’t pass the time with a fire. Coming back later would be a hassle because I had already climbed high to get there, so I was effectively stuck. It would have been nice to have some sort of item to climb in the rain.

The weapons break too easily. The game mechanic of weapons breaking is pretty clever because it forces the player to always try new weapons. However, it feels like they break too soon. Weapon durability is a significant problem early in the game, because the player has very few inventory slots and strong weapons are hard to find. Later in the game, this is less of an issue. I think some better balancing could have been done.

There was no fishing rod. For being such an outdoorsy game, I was truly surprised that there were no fishing rods in BOTW. Link hunts deer with bows and arrows, but he needs to use bombs to catch fish? This struck me as strange and, to a small extent, thwarted the immersive feeling of surviving in the wild. A fishing rod may have been challenging to implement, but I think it could have been possible as a key item like the glider.

I craved more story points. Much of my gameplay narrative shifted between Divine Beast sagas and open exploration. At times, I felt like there was too much to explore without enough reward. I found myself avoiding enemy hideouts late in the game because I simply didn’t need their weapons or spoils. Having more memories to discover would have been awesome, though I suppose that’s what the DLC is for.

Behind the Scenes

Nintendo released a 4-part video series entitled The Making of The Legend of Zelda: Breath of the Wild that’s really cool. Video links are below.

Final Impression

I love The Legend of Zelda: Breath of the Wild. I can’t wait to see where Nintendo takes the franchise from here!

Tutoring: A Lifelong Impact

On Saturday, February 17, 2018, I delivered the keynote address at RIT TutorCon 2018 at the Rochester Institute of Technology in Rochester, NY. I was a student tutor at RIT from 2007-2010. The Academic Support Center asked me to speak about my experiences. Below is the transcript of my speech.

It’s good to be back in Ra-cha-cha! Happy Presidents’ Day weekend, and also Happy Chinese New Year! Let me get a good look at our tutors: If you are a tutor, please stand up.

[Wait for tutors to stand up.]

Great! It’s awesome to see so many of you here today. Is anyone in Computer Science?

Now, remain standing if you have been a tutor for at least one year.

[Wait for people to sit down.]

Not bad. What about two years?

[Wait for more people to sit down.]

Three? [Wait.] Four? [Wait.] Five? [Wait.]

What about ten years? Ten years of tutoring? [Give anyone who remains standing a round of applause, and then ask them to sit down.]

Ten years is a long time! A lot can happen; a lot can change. Here’s a question for you today, though: Will your tutoring make an impact in ten years? [Repeat the question for emphasis.]

Ten years ago, I was one of you. I was in my second year at RIT studying computer science, and I worked for the Academic Support Center and TRIO as a tutor for math, physics, and basically anything that was needed. I would have been sitting in your chair if we had these fancy tutoring conferences back them. Things were quite different a decade ago. Let me drop some knowledge bombs on you for the world in February 2008:

  • We were still on the iPhone 1. iPads did not exist yet.
  • Barack Obama was still seen as a surprise challenger to Hillary Clinton in the 2008 Democratic primaries.
  • The Great Recession was looming but had not yet hit.
  • The Summer Olympics were going to be held in Beijing, China. (Michael Phelps & Usain Bolt)
  • Lady Gaga had not yet released her debut album.

Now, let me contextualize this for RIT:

  • Bill Destler was still in his first year as university president.
  • RIT was still on the quarter system.
  • Park Point was being built.
  • The Simon Center (a.k.a. the “Toilet Bowl”) was being built.
  • The main drop-in study center was the “Math Lab” in Building 1, not Bates.

One thing that looks like it hasn’t changed, though, is Gracie’s. [Assume the audience will laugh.]

By the way, have they knocked down Riverknoll yet? I lived at 232 Kimball Drive. [Assume the audience will laugh or somehow respond.]

A lot happens in ten years. But, will your tutoring have an impact in ten years? Will the tutoring you do today benefit your students years from now? It should.

As college students, life is typically fast-paced. You have classes, you have papers, you have projects; quarters – excuse me, semesters – fly by; and it’s all over after about four years. And, for you, tutoring is just a part of that overall experience. It’s just a part-time job. As we saw earlier, most of you will spend only a few years tutoring before entering your career fields. Personally, I haven’t done any tutoring since 2010. It’s tempting to think that the time you spent tutoring doesn’t matter. So what if you help people finish their homework problems a few times a week? Students come and go anyway. It’s no big deal, right?

Well, if you’re here today at this tutoring conference, I’m pretty sure that tutoring is a big deal to you. You know it’s important. I’d be willing to bet that many of you would do tutoring even if you didn’t get paid – although, the pay is certainly deserved! I want you all to understand that what you do as a tutor will impact your students and will also impact you for the rest of your lives. Tutoring is a vector: I want you to see the line and not just the dot.

Your students come with a myriad of different circumstances. Some are just looking for a healthy environment for doing their homework. Maybe they’re stuck on a tricky physics brain-buster. Others struggle. Some really struggle – and may be one more failure away from academic suspension. But all students have one thing in common: they come to you because they want to do better. Whoever they are, they look to you as tutors to help them succeed. And every question you answer – or rather, every guiding question you turn back to them – puts them further down their paths to success. Today’s practice problems become tomorrow’s degrees. With you, they’ll learn not just the course material but, more importantly, they will learn how to learn. They will learn what questions to ask themselves. They will learn how to find answers using their resources. They will learn to teach themselves. Plutarch once said, “The mind is not a vessel to be filled but a fire to be ignited.”

With my perspective of the line, I want to give you three big ways you can make your tutoring today leave an impact for a lifetime.

First, own your role. As tutors, you have a very unique role with your students: you are peers; you are not professors. That’s a big difference! Professors are experts in their fields with years of experience and dozens of publications. You, as tutors, are students yourselves, just a few more years ahead. You can relate to your students on much more common ground. You’ve taken the same courses. You’ve taken the same tests. You’ve probably even done the very same problems. One of the tutoring tricks is to always work with a student at their level – if they sit at the table, you sit; if they stand at the board, you stand; and unless you’re making a really good example, don’t stand on the table! The equal-level principle also applies to your role as a peer tutor. There’s camaraderie. There’s energy. There’s less embarrassment to ask “stupid” questions. There’s a sense that they can do it because you can do it. So own your role as a peer tutor.

Second, focus on the student and not the problem. The problem is the dot; the student is the line. Tutors aren’t there to solve the world’s problems! Nobody comes to a tutoring center to watch a tutor show off with how much they know or how fast they can solve problems. “Look at how smart I am” – NO! Let’s be real, here: the solution to any given practice problem doesn’t really matter. What does matter is how the student learned to handle problems. Did they make an attempt? Did they look at their formulas? Did they write out their work? Did they persevere when they got stuck? Let me ask you a question: Do you think that I remember specific details to any homework assignments from ten years ago? [Wait for audience response.] Nope! But, I remember that a derivative is a rate of change. And, if I had to solve a derivative again, I’d know exactly where to look in my books to figure it out. That’s how you want your students to be in ten years. Cultivate your students to become independent.

Third, build camaraderie. Your students are already your peers – make them your friends. I don’t have any fancy statistics to share, but I know anecdotally that most students become “repeat customers.” You’ll see them again, and again, and again. Whether intended or not, you will forge relationships with your students. As your tutoring shifts become part of your everyday life, so, too, do the students who show up. Treat every single one of them the way you’d want to be treated. Work to form good relationships. Work to form trust. Be honest when you don’t know something. And furthermore, build camaraderie with your fellow tutors as well! Tutors are a team – each one brings fresh eyes and unique expertise. My specialty? Discrete math and differential equations – what a combo! We, as tutors, are trained in common techniques and share the common burdens to help our students. It’s almost like we have a special, unspoken club. I still keep up with my students and my tutors. I dined with a former student on top of the Space Needle. I partied with another on New Year’s Eve. I’m attending another student’s wedding this summer. A fellow tutor came to mine. So build camaraderie with your students and your fellow tutors.

As I close, I’d like to remind you that you are all in tutoring together. For some of you, this might just be the best job you ever have. I challenge all of you today to make your tutoring count: for now, for ten years from now, and for a lifetime. Tutors don’t make bad students good – tutors make students learn to teach themselves. That is how your tutoring will make a lifelong impact. Thank you.

The Airing of Grievances: BDD

Behavior-Driven Development – one of my favorite blog topics. When done right, it’s a wonderful way to foster better collaboration and automation. When it’s not… well, let’s just say I got a lot of problems with bad BDD practices, and now you’re gonna hear about it!

PROCESS

Treating BDD as a Tool and Not as a Process

BDD is a process – it is a set of tools and practices designed to help teams deliver better software. BDD is not just a test automation framework; the framework is just one of the tools that support BDD. Heck, the word “development” is in the name!

Complaining that Gherkin is Too Technical

Really? Really!? Gherkin is basically just plain language with some buzzwords mixed in! It is specifically designed for non-technical people to handle it! It is not a full-fledged programming language – it is essentially a simple format for behavior specification that automation frameworks can easily parse. The steps are meant to be read like plain English (or any other spoken language) so that better collaboration can happen. If Gherkin is “too technical” for you, then I hate to know what isn’t.

No Buy-In from All Roles

The three major roles on an Agile team, a.k.a the “Three Amigos,” are biz, dev, and test (regardless of fancy names or assignments). For BDD to work well, all three role types must embrace it. Otherwise, collaboration will suffer. BDD is not just a QA thing, it’s for everyone. Biz gets better features in shorter time because requirements were communicated better. Dev wastes less time figuring out what biz wants and gets tests faster. Test can start automating right away since test scenarios are defined from the start in Gherkin. Everybody wins if everybody contributes.

No Three Amigos Meetings

Three Amigos meetings are like dietary fiber supplements: they help a team stay regular with collaboration, or else development gets constipated as engineers start building crap instead of the intended behaviors. Then the crap gets blocked up as the team must rework it, meaning it could be another sprint before there’s a healthy flush of new features. Open conversations in regularly scheduled Three Amigos meetings would have avoided the whole obstruction.

Forcing QA to Write All Behavior Scenarios

BDD is not just QA thing – it is for all roles. Pigeonholing the responsibility of writing behavior scenarios onto QA is not only unfair, it is anti-collaborative. The whole reason for writing scenarios in plain language with Gherkin is to let everyone contribute to feature behavior. Scenarios are primarily about capturing behavior, not writing tests. If tests were the main focus, then engineers could just write test cases using traditional automation frameworks directly in general purpose programming languages like Java or Python. BDD offers the benefits of process efficiency and shifting left when the whole team helps to write behavior scenarios.

GHERKIN

Bad Gherkin

Only you can prevent bad Gherkin. Or I can – via rejected code reviews.

Typos, Poor Grammar, and Inconsistent Formatting

Gherkin needs to be readable. Steps with typos, poor grammar, and inconsistent formatting will still run fine for test automation, but they make it tough to understand the behaviors they describe. Sometimes, they can even make the meaning ambiguous.

No Double-Quotes Around Step Parameters

How do you know if something is a step parameter? “Double quotes” make it easy. However, Gherkin does not enforce double quotes around parameters. It is merely by programmer’s convention, but it’s a really helpful convention indeed.

No Tags

Tags make it super easy to filter scenarios at runtime. No tags? Good luck remembering long paths and names at runtime, or running related scenarios across different feature files together.

More Than 120 Characters per Line

Any longer is too much to comprehend. Either write the step more concisely, or split it apart. Plus, the line may go off the edge of the screen.

More Than 10 Steps per Scenario

Again, any longer is too much to comprehend. Scenarios should be short and sweet – they should concisely describe behavior. Too many steps means the scenario is too imperative or covers more than one behavior.

Multiple Behaviors per Scenario

Scenarios should not have multiple personality disorder: one scenario, one behavior. Don’t break the Cardinal Rule of BDD! So many people break this rule when they first start BDD because they are locked into procedure-driven thinking. Then, when tests fail, nobody knows exactly what behavior is the culprit. One scenario, one behavior.

Out-of-Order Step Types

Givens, Whens, and Thens each serve a specific, ordered purpose: Given some initial state, When actions are taken, Then verify an expected outcome. Jumbling them up ruins their meaning. Furthermore, duplicate When-Then pairs indicate multiple behaviors per scenario. And don’t just reassign step types to skirt the strict-ordering rule. Do it right – put integrity into the steps!

Gigantic Tables

Have you ever seen an Examples table with 13 columns? Or maybe 517 rows? I have. The horror, the horror! Tables that big make scenarios lose any semblance of specification-by-example. Make sure table rows and columns are actually needed. Use key-value lookups if the data is too gritty.

Being Imperative Rather Than Declarative

Given I’m logged into the app, when I click here, and I click there, and I type P, and I type L, and I type E, and I type A, and I type S, and I type E, and I type D, and I type O, and I type N, and I type T, and I type W, and I type R, and I type I, and I type T, and I type E, and I type S, and I type C, and I type E, and I type N, and I type A, and I type R, and I type I, and I type O, and I type S, and I type L, and I type I, and I type K, and I type E, and I type T, and I type H, and I type I, and I type S, then go directly to jail, and do not pass GO, and do not collect $200. Steps should focus more on what than how.

Prefixing Existing Test Procedure Steps with Gherkin Buzzwords

Let’s just take our existing test procedures from a tool like HP QualityCenter or ALM and put the words “Given,” “When,” and “Then” in front of every step. Ta-da! We’re now doing BDD! …WRONG!! I kid you not, I have see this happen. These people clearly never took BDD 101. It hurts to see.

AUTOMATION

Unorganized Step Definitions

Programmers like to throw their step definition methods anywhere. Add ’em to an unrelated existing class? Create a whole new class for only two new steps? Mix up the types? Who cares! Don’t bother to alphabetize them, either. Well, that’s how tech debt happens. That’s how duplicate steps get written, because originals can’t be found. Imagine a library without the Dewey Decimal System – that’s what an unorganized step def collection will be.

Putting Cleanup Code in Then Steps

Cleanup code belongs in After hooks, where it will be run no matter what fails during the scenario. Writing Then steps to do cleanup not only breaks step type integrity, the cleanup code will not run if a previous step aborts!

Catching and Burying All Exceptions

Here’s something I see all the time in automation code (and not just for BDD):

// FYI - This is Java, but the same thing can happen in any language
@When("^do something$")
public void doSomething() throws Throwable {
  try {
    callStuff();
  }
  catch (Exception e) {
    System.out.println(e.getMessage());
  }
}

The entirety of a step (or even a whole test) is surrounded by a try-catch that catches every exception. THIS STEP CAN NEVER REGISTER A FAILURE! Even if there was a failed assertion or, worse, an exception that ought to abort the test, it will get caught and buried with not much more than a slight whimper in the log. In this case, the test will carry forth to the next step, which will probably not work, either. I’ve seen projects with this sort of exception handling around every single step definition. In modern test frameworks, the framework will catch all exceptions at the highest level, register the test as failed, and move on safely to the next test. There is no need to catch any exception, unless the test can be recovered.

Changing Steps Without Testing Affected Scenarios

Sharing steps is a wonderful thing, but changing steps without testing all scenarios that use them is a terrible thing. I’ve seen people change step text or step def code and test only their new scenarios. Meanwhile, in the continuous integration environment, a dozen other tests using those steps started failing. (Hell, I’ve seen people push code that doesn’t even compile, but that’s another grievance.)

Multiple Names for the Same Step

Just because you can do something doesn’t mean you should. Different names for the same step may be useful for readability, but please keep the name variants limited.

No Dependency Injection

Dependency injection is the best way to share objects in an automation framework. (Singletons work well, too, but DI allows more careful control of scope.) Many frameworks like Cucumber-JVM even integrate with existing DI frameworks like PicoContainer and Spring. DON’T MAKE NON-CONSTANT VARIABLES GLOBAL! DON’T BLINDLY MAKE THINGS “STATIC” JUST TO SHARE THEM! Globals (or “statics” in Java/C# like languages) are dangerous: they can be easily misused, they are a nightmare to trace, and they can break multithreaded execution. Just use the appropriate design pattern: dependency injection.

The Airing of Grievances: Agile

Agile has essentially replaced the Waterfall model as the “right” software development methodology. It’s a really great process when it’s done right, but people ruin it when they do it wrong. And, oh, how badly it can go wrong. I got a lot of problems with bad Agile practices, and now you’re gonna hear about it!

Breaking the Rules

Agile is a lot like the board game Monopoly. The rules are long and complicated, but they are designed to make the game efficient. However, for some reason, everyone insists on making up their own rules for the game, rather than following the official instructions. For example, players won’t put a property up for auction when they land on it and refuse to buy it, or they will build houses before securing a monopoly. Then, as a result, the game goes on forever and loses its fun. In Agile, every organization seems to want to do things their own special way (as many of these grievances describe), and it almost never goes well when they do. The rules are not meant to be broken, and if they are, there will be consequences.

Going Rogue

Agile is meant to keep people focused on the most important tasks. Much time is spent planning and pivoting to stay on top of priorities. Team members should not deviate from committed work. Don’t go rogue! Don’t work on uncommitted tasks! If something is absolutely pressing, then talk with the scrum master to change the commitments.

Teams that are Too Big

How big is your Agile team? If the answer has more than one digit, then the team is too darn big. The ideal size is 5-9 people because communication becomes too hard with more. Large teams just don’t scale – it’s the law of diminishing returns.

Long Meetings

Nobody wants to be stuck in a long, boring meeting. While there are many Agile ceremonies (planning, grooming, stand-up, review, and retrospective), their meetings are meant to be efficient and productive. Stand-ups should be 15 minutes tops – nobody should ever need to give more than three sentences for their status, and nobody really wants to hear anything longer anyway! People should come prepared for planning and grooming so they don’t literally take all day. Demos should be short and sweet. Keep things moving!

Putting People on More Than One Team

Nobody should be cursed to provide deliverables for more than one Agile team. That’s not fair to the individual, who must spend double-duty in meetings, nor is it fair to the teams, who don’t have a dedicated resource for their work. It applies to every role: developer, tester, product owner, or scrum master. It also burns people out very quickly.

Too Many Top Priorities

I was once part of an Agile team where the product owner issued about a dozen “top priorities.” For. Every. Sprint. Our team had no clue what was really important.

Agonizing Over Story Points

Story points are meant to be sizing estimates for velocity. They don’t need to be perfectly accurate. They shouldn’t track hours. Don’t make big fights over it. Don’t go back and change values. Don’t twist planning poker into a political gambit. PLEASE!

Missing User Story Descriptions

The user story is the primary work artifact. It tells how a new feature should work from the perspective of the user… or, at least it should. If your user story contains just one line (like saying “Build the profile page”), then you just might be doing it wrong. Write user stories in the “As a ___, I want ___, so that ___” format, and provide extra descriptions to help the team understand what the story covers. Non-descriptive stories lead to poorly developed features.

Missing Acceptance Criteria

How do we know when a story is complete? If there’s no acceptance criteria, we don’t! Testers also won’t know what to check. Please write helpful acceptance criteria. A bullet list is fine, and Gherkin would be even better.

Not Including Testing and Automation in the Definition of Done

No. No. No. No. No. No. NO! A story is not complete if it is not tested. It must not be accepted without tests passing and automated. Otherwise, be prepared for an avalanche of technical debt as bugs pile up and the team can’t keep up. The premise of Agile is to deliver small, working features in iterations. Testing must be included! Don’t create separate stories for testing. Don’t push it off to the next sprint. If a team cannot get testing done, then perhaps it should increase story point sizings to include testing and/or commit to less work during a sprint.

Blaming QA for Incomplete Stories

I once heard a developer say bluntly to my automation team, “QA is the bottleneck.” Don’t shoot the messenger! Tests fail because the product under test has problems. Many times, testers don’t even receive builds until very late in the sprint. When stories don’t get done, don’t start a blame game – it’s the whole team’s fault. Try shifting left (perhaps by using BDD) or committing to less work per sprint.

Ignoring Technical Debt

Technical debt is the cost of consequences from poor development decisions. Examples may include: using single-threading when multi-threading is needed, avoiding design patterns, and even building up a test automation framework. Product owners don’t seem to like tech debt tasks because they don’t deliver new features. Unfortunately, tech debt will often cripple a team’s ability to deliver new features – pay now or pay later. Don’t ignore tech debt!

Confusing Agile with “Short Waterfall”

Agile is meant to be a process paradigm shift. It is not meant to be a condensed version of the Waterfall model. Sprints should be short. Responsibilities should be shared. Teams should be self-empowered. Break down silos and become truly Agile!

Using “Agile” and “Lean” Interchangeably

The Lean Startup is a methodology for starting a new business using minimal overhead and reacting quickly to lessons learned. It involves using Agile for product development, but it encompasses so much more than just Agile. Don’t use the terms interchangeably! Get on point with your buzzword bingo game.

Misusing the Term “Continuous Integration”

A nightly build is not CI. A weekly regression run is not CI. Manually-triggered tests are not CI. Manual deployments are not CI. Hand-written test reports are not CI. Don’t lie to yourself – CI is continuous integration, and everything must be automatic.

Forcing Scrum When Kanban May Be Better

Scrum is probably the most widely used Agile process, to the point where most people presume “Agile” means “Scrum.” However, Scrum is not appropriate for all teams. Kanban is a much better process when work items must be done “just in time” – like tech support tickets, build deployments, system maintenance, or emergency recoveries. Good candidates for Kanban are IT help desks and DevOps teams. I’ve used Kanban on automation tools/frameworks teams very successfully. Don’t shoehorn everyone into Scrum.

Hanging Agile Manifesto Posters on the Wall

What are you, Communist?

Complaining about Agile

Complaining doesn’t make it better! Honestly, in my experience, the worst complainers are old-school people who just don’t like change. Then, problems become a self-fulfilling prophecy. Or, they try to break rules and then gripe when things don’t work. If your complaint is about Agile in general, then go take a long, hard look in the mirror. However, if you find a problem in how your team is doing Agile, then bring it up during the retrospective – that’s Agile’s auto-correct mechanism. Complaining for complaint’s sake drags everybody down.

The Airing of Grievances: Selenium WebDriver

Selenium WebDriver is the de facto standard for Web UI automation. It’s a great tool, but like anything good, it can also be misused. And that’s where I have grievances. I got a lot of problems with Selenium WebDriver abuses, and now you’re gonna hear about it!

WebDriver “Unit Tests”

“WebDriver unit tests” are like square circles – definitionally, they are logical fallacies. In my books, a unit test must be white box, meaning it has direct access to the product code. However, Web UI tests using WebDriver are inherently black box tests because they are interacting with an actively running website. Thus, they must be above-unit tests by definition. Don’t call them unit tests!

Making Every Test a Web Test

NO! The Testing Pyramid is vital to a healthy overall testing strategy. Web tests are great because they test a website in the ways a user would interact with it, but they have a significant cost. As compared to lower-level tests, they are more fragile, they require more development resources, and they take much more time to run. Browser differences may also affect testing. Furthermore, problems in lower level components should be caught at those lower levels! Sure, HTTP 400s and 500s will appear at the web app layer, but they would be much faster to find and fix with service layer tests. Different layers of testing mitigate risk at their optimal returns-on-investment.

No WebDriver Cleanup

Every WebDriver instance spawns a new system process for “driving” web browser interactions. When the test automation process completes, the WebDriver process may not necessary terminate with it. It is imperative that test automation quits the WebDriver instance once testing is complete. Make sure cleanup happens even when abortive exceptions occur! Otherwise, zombie WebDriver processes may continue on the test machine, causing any number of problems: locked files and directories, high memory usage, wasted CPU cycles, and blocked network ports. These problems can cripple a system and even break future test runs, especially on shared testing machines (like Jenkins nodes). Please, only you can stop the zombie apocalypse – always quit WebDriver instances!

Using “Close” Instead of “Quit”

Regardless of programming language, the WebDriver class has both “close” and “quit” methods. “Close” will close the current browser tab or window, while “quit” will close all windows and terminate the WebDriver process. Make sure to quit during final cleanup. Doing only a close may result in zombie WebDriver processes. It’s a rookie mistake.

Not Optimizing Setup/Cleanup with Service Calls

Web tests are notoriously slow. Whenever you can speed them up, do it! Some tests can be optimized by preparing initial state with service calls. For example, let’s say a user visiting a car dealership website needs to have favorite cars pre-selected for a comparison page test. Rather than navigating to a bunch of car pages and clicking a “favorite” icon, make a setup routine that calls a service to select favorites. Not all tests can do this sort of optimization, but definitely do it for those that can!

Web Elements with No ID

Developers, we need to talk – give every significant element a unique ID. PLEASE! WebDriver calls are so much easier to write and so much more robust to run when locator queries can use IDs instead of CSS selectors or XPaths. Let’s pick ID names during our Three Amigos meetings so that I can program the tests while you develop the features. Determining what elements are import should be easy based on our wireframes. You will save us automators so much time and frustration, since we won’t need to dig through HTML and wonder why our XPaths don’t work.

Changing Web Elements Without Warning

Hey, another thing, developers – don’t change the web page structure without telling us! WebDriver locator queries will break if you change the web elements. Even a seemingly innocuous change could wipe out hundreds of tests. Automation effort is non-trivial. Changes must be planned and sized with automation considerations in mind.

Not Using the Page Object Model

The Page Object Model is a widely-used design pattern for modeling a web page (or components on a web page) as an object in terms of its web elements and user interactions with it. It abstracts Web UI interactions into a common layer that can be reused by many different tests. (The Screenplay pattern, also good, is an evolution of the Page Object Model; tutorial here.) Not using the Page Object Model is Selenium suicide. It will result in rampant code duplication.

Demonizing XPath

XPaths have long been criticized for being slower than CSS selectors. That claim is outdated baloney. In many cases, XPaths outperform CSS selectors – see here, here, and here. Another common complaint is that XPath syntax is more complicated than CSS selector syntax. Honestly, I think they’re about the same in terms of learning curve. XPaths are also more powerful that CSS selectors because they can uniquely pinpoint any element on the page.

Inefficient Web Element Access

Web element IDs make access extremely efficient. However, when IDs are not provided, other locator query types are needed. It is always better to use locator queries to pinpoint elements, rather than to get a list of elements (or even a parent/child chain) to traverse using programming code. For example, I often see code reviews in which an XPath returns a list of results with text labels, and then the programming code (C# or Java or whatever) has a for loop that iterates over each element in the list and exits when the element with the desired label is found. Just add “[text()=’desired text’]” or “[contains(text(), ‘desired text’)]” to the XPath! Use locator queries for all they’re worth.

Interacting with Web Elements Before the Page is Ready

Web UI test automation is inherently full of race conditions. Make sure the elements are ready before calling them, or else face a bunch of “element not found” exceptions. Use WebDriver waits for efficient waiting. Do not use hard sleeps (like Java’s Thread.sleep).

Untuned Timeouts

WebDriver calls need timeouts, or else they could hang forever if there is a problem. (Check online docs for default timeout values.) Timeout value ought to be tuned appropriately for different test environments and different websites. Timeouts that are too short will unnecessarily abort tests, while timeouts that are too long will lengthen precious test runtime.