On April 22, 2021, I delivered a talk entitled “Managing the Test Data Nightmare” at SauceCon 2021. SauceCon is Sauce Labs’ annual conference for the testing community. Due to the COVID-19 pandemic, the conference was virtual, but I still felt a bit of that exciting conference buzz.
My talk covers the topic of test data, which can be a nightmare to handle. Data must be prepped in advance, loaded before testing, and cleaned up afterwards. Sometimes, teams don’t have much control over the data in their systems under test—it’s just dropped in, and it can change arbitrarily. Hard-coding values into tests that reference system tests can make the tests brittle, especially when running tests in different environments.
In this talk, I covered strategies for managing each type of test data: test case variations, test control inputs, config metadata, and product state. I also covered how to “discover” test data instead of hard-coding it, how to pass inputs into automation (including secrets like passwords), and how to manage data in the system. After watching this talk, you can wake up from the nightmare and handle test data cleanly and efficiently like a pro!
Here are some other articles I wrote about test data:
Do you want to learn how to automate tests in Python? Python is one of the best languages for test automation because it is easy to learn, concise to write, and powerful to scale. These days, there’s a wealth of great content on Python testing. Here’s a brief reference to help you get started.
If you want to roll up your sleeves, check out Test Automation University. I developed a “trifecta” of Python testing courses for TAU with videos, transcripts, quizzes, and example code. You can take them for FREE!
Have you ever seen those “@” tags on top of Python functions and classes? Those are decorators – functions that wrap around other functions. Confusing? At first, but they’re easy with practice. Useful? Very!
Hello, PyTexas 2020! It’s Pandy Knight here. I’m the Automation Panda, and I’m a big Python fan, just like y’all.
Have you ever seen those “@” tags on top of Python functions? Maybe you’ve seen them on top of methods and classes, too. Those are decorators, one of Python’s niftiest language features. Decorators are essentially wrappers – they wrap additional code around existing definitions. When used right, they can clean up your code better than OxiClean! Let’s learn how to use them.
So, here’s a regular old “hello world” function. When we run it, …
…It prints “Hello World!” Nothing fancy here.
Now, let’s take that function…
…And BAM! Add a decorator. Using this “@” sign, we just added a decorator named “tracer” to “hello_world”. So, what is this decorator?
“Tracer” is just another function. But, it’s special because it takes in another function as an argument!
Since “tracer” decorates “hello_world”, the “hello_world” function is passed into “tracer” as an argument. Wow!
So, what’s inside “tracer”?
This decorator has an inner function named “wrapper”. Can you even do that? With Python, yes, you can! The “wrapper” function prints “Entering”, calls the function originally passed into the decorator, and then prints “Exiting”.
When “tracer” decorates “hello_world”, that means “hello_world” will be wrapped by “Entering” and “Exiting” print statements.
Finally, the decorator returns the new “wrapper” function. Any time the decorated function is called, it will effectively be replaced by this new wrapper function.
So, when we call “hello_world”, the trace statements are now printed, too. Wow! That’s amazing. That’s how decorators work.
[Slide] Decorators [Slide] wrap [Slide] functions [Slide] around [Slide] functions!
Think about them like candy bars. The decorator is like the foil wrapper, and the decorated function is like the chocolate inside.
But how is this even possible? That decorator code looks confusing!
Decorators are possible because, in Python, functions are objects. In fancy language, we say functions are “first-order” values. Since functions are just objects, …
…We can pass them into other functions as arguments, …
…define new functions inside existing functions, …
…and return a function from a function.
This is all part of a paradigm called “Functional Programming.” Python supports functional programming because functions can be treated like objects. That’s awesome!
So, using functions as objects, decorators change how functions are called.
Decorators create an “outer” decorator function around an “inner” decorated function. Remember, the outer function is like the foil wrapper, and the inner function is like the chocolate.
Creating an outer function lets you add new code around the inner function. Some people call this “advice.” You can add advice before or after the inner function. You could even skip the inner function!
The best part is, decorators can be applied to any function. They make sharing code easy so you don’t repeat yourself!
Decorators are reminiscent of a paradigm called “Aspect-Oriented Programming,” in which code can be cleverly inserted before and after points of execution. Neat!
So remember, decorators wrap functions around functions, like candy bars!
Hold on, now! We have a problem in that Python code!
If the “wrapper” function effectively replaces “hello_world”, then what identity does “hello_world” report?
Its name is “wrapper”…
And its help is also “wrapper”! That’s not right!
Never fear! There’s an easy solution. The “functools” module provides a decorator named “wraps”. Put “functools.wraps” on the “wrapper” function and pass in the inner function object, and decorated functions once again show the right identity. That’s awesome.
But wait, there’s another problem!
How do decorators work with inputs and outputs? What if we decorate a function with parameters and a return value?
If we try to use the current “tracer”, …
…We get an error! Arguments broke it!
We can fix it! First, add “star args” and “star-star k-w-args” to the “wrapper” function’s parameters, and then pass them through to the inner function. This will make sure all arguments go through the decorator into the decorated function.
Then, capture the inner function’s return value and return it from the “wrapper” function. This makes sure return values also pass through. If the inner function has no return value, don’t worry – the decorator will pass through a “None” value.
When we call the function with the updated “tracer”, …
…we see tracing is now successful again!
When we check the return value, …
…it’s exactly what we expect. It works!
Wow, that’s awesome!
But wait, there’s more!
You can write a decorator to call a function twice!
Start with the decorator template…
…and call the inner function twice! Return the final return value for continuity.
BAM! It works!
But wait, there’s more!
You can write a timer decorator!
Start with the template, …
…call the inner function, …
…and surround it with timestamps using the “time” module!
BAM! Now you can time any function!
But wait, there’s more!
You can also add more than one decorator to a function! This is called “nesting”. Order matters. Decorators are executed in order of closeness to the inner function. So, in this case, …
…”call_twice” is applied first, and then “timer” is applied.
If these decorators are reversed, …
…then each inner function call is timed. Cool!
But wait, there’s more!
You can scrub and validate function arguments! Check out these two simple math functions.
Create a decorator to scrub and validate inputs as integers.
Add the wrapper function, and make sure it has positional args.
Then, cast all args as ints before passing them into the inner function.
Now, when calling those math functions, all numbers are integers! Using non-numeric inputs also raises a ValueError!
But wait, there’s more!
You can create decorators with parameters! Here’s a decorator that will repeat a function 5 times.
The “repeat” function is a little different. Instead of taking in the inner function object, it takes in the parameter, which is the number of times to repeat the inner function.
Inside, there’s a “repeat_decorator” function that has a parameter for the inner function. The “repeat” function returns the “repeat_decorator” function.
Inside “repeat_decorator” is the “wrapper” function. It uses “functools.wraps” and passes through all arguments. “repeat_decorator” returns “wrapper”.
Finally, “wrapper” contains the logic for calling the inner function multiple times, according to the “repeat” decorator’s parameter value.
Now, “hello_world” runs 5 times. Nifty!
But wait, there’s more!
Decorators can be used to save state! Here’s a decorator that will count the number of times a function is called.
“count_calls” has the standard decorator structure.
Outside the wrapper, a “count” attribute is initialized to 0. This attribute is added to the wrapper function object.
Inside the wrapper, the count is incremented before calling the inner function. The “count” value will persist across multiple calls.
Initially, the “hello_world” count value is 0.
After two calls, the count value goes up! Awesome!
But wait, there’s more!
Decorators can be used in classes! Here, the “timer” decorator is applied to this “hello” method.
As long as parameters and return values are set up correctly, decorators can be applied equally to functions and methods.
Decorators can also be applied directly to classes!
When a decorator is applied to a class, it wraps the constructor.
Note that it does not wrap each method in the class.
Since decorators can wrap classes and methods in addition to functions, it would technically be more correct to say that decorators wrap callables around callables!
So all that’s great, but can decorators be tested? Good code must arguably be testable code. Well, today’s your lucky day, because yes, you can test decorators!
Testing decorators can be a challenge. We should always try to test the code we write, but decorators can be tricky. Here’s some advice:
First, separate tests for decorator functions from decorated functions. For decorator functions, focus on intended outcomes. Try to focus on the “wrapper” instead of the “inner” function. Remember, decorators can be applied to any callable, so cover the parts that make decorators unique. Decorated functions should have their own separate unit tests.
Second, apply decorators to “fake” functions used only for testing. These functions can be simple or mocked. That way, unit tests won’t have dependencies on existing functions that could change. Tests will also be simpler if they use slimmed-down decorated functions.
Third, make sure decorators have test coverage for every possible way it could be used. Cover decorator parameters, decorated function arguments, and return values. Make sure the “name” and “help” are correct. Check any side effects like saved state. Try it on methods and classes as well as functions. With decorators, most failures happen due to overlooked edge cases.
Let’s look at a few short decorator tests. We’ll use the “count_calls” decorator from earlier.
There are two decorated functions to use for testing. The first one is a “no operation” function that does nothing. It has no parameters or returns. The second one is a function that takes in one argument and returns it. Both are very simple, but they represent two equivalences classes of decoratable functions.
The test cases will verify outcomes of using the decorator. For “count_calls”, that means tests will focus on the “count” attribute added to decorated functions.
The first test case verifies that the initial count value for any function is zero.
The second test calls a function three times and verifies that count is three.
The third test exercises the “same” function to make sure arguments and return values work correctly. It calls the “same” function, asserts the return value, and asserts the count value.
This collection of tests is by no means complete. It simply shows how to start writing tests for decorators. It also shows that you don’t need to overthink unit tests for decorators. Simple is better than complex!
Up to this point, we’ve covered how to write your own decorators. However, Python has several decorators available in the language and in various modules that you can use, absolutely free!
Decorators like “classmethod”, “staticmethod”, and “property” can apply to methods in a class. Frameworks like Flask and pytest have even more decorators. Let’s take a closer look.
Let’s start by comparing the “classmethod” and “staticmethod” decorators. We’ll revisit the “Greeter” class we saw before.
The “classmethod” decorator will turn any method into a “class” method instead of an “instance” method. That means this “hello” method here can be called directly from the class itself instead of from an object of the class. This decorator will pass a reference to the class into the method so the method has some context of the class. Here, the reference is named “c-l-s”, and the method uses it to get the class’s name. The method can be called using “Greeter.hello”. Wow!
The “staticmethod” decorator works almost the same as the “classmethod” decorator, except that it does not pass a reference to the class into the method.
Notice how the method parameters are empty – no “class” and no “self”. Methods are still called from the class, like here with “Greeter.goodbye”. You could say that “staticmethod” is just a simpler version of “classmethod”.
Next, let’s take a look at the “property” decorator. To show how to use it, we’ll create a class called “Accumulator” to keep count of a tally.
Accumulator’s “init” method initializes a “count” attribute to 0.
An “add” method adds an amount to the count. So far, nothing unusual.
Now, let’s add a property. This “count” method has the “property” decorator on it. This means that “count” will be callable as an attribute instead of a method, meaning that it won’t need parentheses. It is effectively a “getter”. The calls to “count” in the “init” and “add” methods will actually call this property instead of a raw variable.
Inside the “count” property, the method returns an attribute named “underscore-count”. The underscore means that this variable should be private. However, this class hasn’t set that variable yet.
That variable is set in the “setter” method. Setters are optional for properties. Here, the setter validates that the value to set is not negative. If the value is good, then it sets “underscore-count”. If the value is negative, then it raises a ValueError.
“underscore-count” is handled internally, while “count” is handled publicly as the property. The getter and setter controls added by the “property” decorator let you control how the property is handled. In this class, the setter protects the property against bad values!
So, let’s use this class. When an Accumulator object is constructed, its initial count is 0.
After adding an amount to the object, its count goes up.
Its count can be directly set to non-negative values. Attempting to set the count directly to a negative value raises an exception, as expected. Protection like that is great!
Python packages also frequently contain decorators. For example, Flask is a very popular Web “micro-framework” that enables you to write Web APIs with very little Python code.
Here’s an example “Hello World” Flask app taken directly from the Flask docs online. It imports the “flask” module, creates the app, and defines a single endpoint at the root path that returns the string, “Hello, World!” Flask’s “app.route” decorator can turn any function into a Web API endpoint. That’s awesome!
Another popular Python package with decorators is pytest, Python’s most popular test framework.
One of pytest’s best features is the ability to parametrize test functions to run for multiple input combinations. Test parameters empower data driven testing for wider test coverage!
To show how this works, we’ll use a simple test for basic arithmetic: “test addition”. It asserts that a plus b equals c.
The values for a, b, and c must come from a list of tuples. For example, 1 plus 2 equals 3, and so forth.
The “pytest.mark.parametrize” decorator connects the list of test values to the test function. It runs the test once for each tuple in the list, and it injects the tuple values into the test case as function arguments. This test case would run four times. Test parameters are a great way to rerun test logic without repeating test code.
So, act now, before it’s too late!
When should you use decorators in your Python code?
Use decorators for aspects.
An aspect is a special cross-cutting concern. They are things that happen in many parts of the code, and they frequently require repetitive calls.
Think about something like logging. If you want to add logging statements to different parts of the code, then you need to write multiple logging calls in all those places. Logging itself is one concern, but it cross-cuts the whole code base. One solution for logging could be to use decorators, much like we saw earlier with the “tracer” decorator.
Good use cases for decorators include logging, profiling, input validation, retries, and registries. These are things that typically require lots of extra calls inserted in duplicative ways. Ask yourself this:
Should the code wrap something else? If yes, then you have a good candidate for a decorator.
However, decorators aren’t good for all circumstances. You should avoid decorators for “main” behaviors, because those should probably be put directly in the body of the decorated function. Avoid logic that’s complicated or has heavy conditionals, too, because simple is better than complex. You should also try to avoid completely side-stepping the decorated function – that could confuse people!
Ask yourself this: is the code you want to write the wrapper or the candy bar itself? Wrappers make good decorators, but candy bars do not.
I hope you’ve found this infomercial about decorators useful! If you want to learn more, …
…check out this Real Python tutorial by Geir Arne Hjelle named “Primer on Python Decorators”. It covers everything I showed here, plus more.
Thank you very much for listening! Again, my name is Pandy Knight – the Automation Panda and a bona fide Pythonista. Please read my blog at AutomationPanda.com, and follow me on Twitter @AutomationPanda. I’d love to hear what y’all end up doing with decorators!
Although the news of PyCon’s cancellation is not surprising, it is nevertheless devastating for members of the Python community. Here’s why it hurts, from the perspective of a full-hearted Pythonista, and here’s what we can do about it.
Python is Community-Driven
A frequent adage among Pythonistas is, “Come for the language, and say for the community.” I can personally attest to this statement for myself. When I started using Python in earnest in 2015, I loved how clean, concise, and powerful the language was. I didn’t fully engage the Python community until PyCon 2018, but once I did, I never left because I felt like I became part of something greater than just a bunch of coders.
Python is community-driven. There’s no major company behind the Python language, like Oracle for Java or Microsoft for .NET. Pythonistas keep Python going, whether that’s by being a Python language core developer, a third-party package developer, a conference organizer, a meetup volunteer, a corporate sponsor, or just a coder using Python for projects. And the people in the community are awesome. We help each other. We support each other. We eschew arrogance, champion diversity, and practice inclusivity.
PyCon US is the biggest worldwide Python event of the year. Thousands of Pythonistas from around the world join together for days of tutorials, talks, and sprints. This is the only time that many of us get to see each other in person together. It’s also the only way some of us would have ever met each other. I think of my good mate Julian, co-founder of PyBites. We met by chance at PyCon 2018 in the “hallway track” (meaning, just walking around and meeting people), and we hit it off right away. Julian lives in Australia, while I live in the United States. We probably would never have met outside of PyCon. Since then, we’ve done video chats together and promoted each other’s blogs. We spent much time together at PyCon 2019 and hoped to have another blast at PyCon 2020. We even had plans for a bunch of us content developers to get together to party. Unfortunately, that time together must be postponed until 2021.
There are several other individuals I could name in addition to Julian, too. I’m sure there are several other groups of friends throughout the community who look to PyCon as the time to meet. Losing that opportunity is heartbreaking.
PyCon is a Spectacle
PyCon itself is not just a conference – it’s a spectacle. PyCon is the community’s annual celebration of creativity, innovation, and progress. Talks showcase exciting projects. Tutorials shed deep expertise on critical subjects. Sprints put rocket boosters underneath open source projects to get work done. Online recordings become mainstay resources for the topics they cover. Becoming a speaker at PyCon is truly a badge of honor. Sponsors shower attendees with more swag than a carry-on bag can hold: t-shirts, socks, stickers, yo-yos, autographed books, iPads, water bottles, gloves, Pokémon cards; the list goes on and on. Many sponsors even host after-parties with dinner and drinks. All of these activities combined make PyCon much more than just another conference or event.
PyCon is truly a time to shine. Anyone who attends PyCon catches the magic in the air. There’s an undeniable buzz. And the anticipation leading up to PyCon can be unbearable. It’s like when kids go to Disney World. I can’t tell you how many friends I’ve encouraged to go to PyCon.
At PyCon 2020, we had much to celebrate. Python is now one of the world’s most popular programming languages, according to several surveys. Python 2 reached end-of-life on January 1. There are more Python projects and resources than ever before. 2020 is also the start of a new decade. We can still celebrate them, but not en masse at PyCon this year.
PyCon Supports the PSF
The Python Software Foundation (PSF) is the non-profit organization that supports the Python language and community. Here’s what they do, copied directly from their website:
The Python Software Foundation (PSF) is a 501(c)(3) non-profit corporation that holds the intellectual property rights behind the Python programming language. We manage the open source licensing for Python version 2.1 and later and own and protect the trademarks associated with Python. We also run the North American PyCon conference annually, support other Python conferences around the world, and fund Python related development with our grants program and by funding special projects.
PyCon is a major source of revenue for the PSF. I don’t know the ins and outs of the numbers, but I do know that cancelling PyCon will financially hurt the PSF, which will then affect what the PSF can do to carry out its mission. That’s no bueno.
What Can We Do?
Python is community-driven, and we are not powerless. Here are some things we can do as Pythonistas in light of PyCon 2020’s cancellation:
Support the Python Software Foundation. Openly and publicly thank the PSF for everything they have done. Offer heartfelt sympathies for the incredibly tough decisions they’ve had to make in recent weeks, because they made the unquestionably right decision here.
Join the Python Software Foundation. Anyone can become a member. There are varying levels of membership and commitment. Check out the PSF Membership FAQ for more info. Donations will greatly help the PSF through this tough time.
Engage your local Python community. The Python community is worldwide. Look for a local meetup. Attend regional Python conferences if possible – PyCon isn’t the only Python conference! The closest ones to where I live are PyGotham, PyOhio, and PyTennessee, and I’m helping to re-launch PyCarolinas.
Engage the online Python community. Even though many of us are practicing social distancing due to COVID-19, we can still keep in touch through the Internet. Support each other. Be intentional with good communication. Personally, I started using the hashtag #PythonStrong on Twitter.
Stay safe. COVID-19 is serious. Wherever you are, be smart and do the right things. For folks like me in the United States, that means social distancing right now.
Attend PyCon 2021. Since PyCon 2020 will be cancelled, we ought to make PyCon 2021 the best PyCon ever.
PyCon 2020’s cancellation is devastating but necessary. We shall overcome. Stay safe out there, Pythonistas. Stay #PythonStrong!
Hello World! I’d like to give an update on the PyCarolinas 2020 conference, since we’ve been quiet for quite some time. I’ll share what we’ve done and a new vision for where we want to go, especially given current world events.
How We Got Started
Calvin Spealman founded “PyCarolinas” in 2012 with the first (and so far only) conference at UNC Chapel Hill. The only other Python conference held in the Carolinas since then was PyData Carolinas 2016, hosted by IBM. Despite having several talented Pythonistas in both North and South Carolina, various factors prevented the return of either conference.
I first encountered the Python community when I delivered my first conference talk ever at PyData Carolinas 2016. However, I really became engaged at PyCon 2018, an experience that forever changed my life. I started speaking at several Python conferences around North America. The people I met became dear friends, and the ideas I learned inspired me to be a better Pythonista. However, one thing disappointed me: my home state didn’t have a regional Python conference. I wanted to bring the awesomeness of a Python conference to my backyard so that others could join the fun.
During PyCon 2019, I shared this idea with some friends, and every one of them said that we should make it happen. A few of us attended an open space for conference organizers to swap ideas. Dustin Ingram then invited me to give a call-to-action for a PyCarolinas 2020 conference on the big stage during the “parade of worldwide conferences.” Immediately thereafter, I held an open space for PyCarolinas to kick things off, and dozens of people attended. We created a Slack room, launched a newsletter, and started a Twitter storm. I got in touch with Calvin so we could formally plan things together. Calvin secured a venue at the Red Hat Annex for June 20-21. We even created a logo and took Code of Conduct training by invitation of our wonderful PyGotham friends. Things were looking bright.
Well, What Happened?
Life happened. From November until now, I personally had to handle several personal and family matters, in addition to holidays, my full-time job, and various commitments. You can read the full story here. Calvin also had things come up. As a result, PyCarolinas progress was minimal. We brought together a community, but we failed to meet critical milestones. I personally take responsibility for those failures.
There’s also a new monkey wrench in our plans: COVID-19. The coronavirus is starting to spread throughout the United States, and North Carolina is already in a state of emergency due to multiple local cases. Other conferences like SXSW 2020 and E3 have been canceled. At the time of writing this article, PyCon 2020 might be canceled or postponed. We just don’t know how things will be by June. We would hate to put a lot of work into PyCarolinas 2020 if it could be canceled due to COVID-19, especially when we are already behind schedule.
A New Way Forward
Personally, I was ready to give up and recommend that we cancel PyCarolinas 2020. Then, while returning from PyTennessee 2020, I had a stroke of inspiration:
What if we made PyCarolinas 2020 an “unconference”?
Traditional conferences take a lot of top-down planning and hard commitments, which is not something we can or should do right now. Unconferences, on the other hand, are participant-driven. Their organization is lean: provide a space for people to gather, collaborate, and cross-pollinate.
Here’s the new vision I’d like to cast for a PyCarolinas 2020 Unconference:
One day only: Saturday, June 20 at Red Hat Annex
Lightning talks only: no lengthy CFP; informal sign-ups beforehand
Maybe a keynote speaker
Open collaboration spaces in the other rooms
Set aside time for organizers to seriously plan PyCarolinas 2021
Limit sponsorships for simplicity
Uphold the Python community’s Code of Conduct
Offer only about 100 tickets to keep the event small
Encourage local and regional attendance
Empower the Python community to be awesome!
Furthermore, I would like to offer tickets for FREE! Free tickets would allow anyone to come, and they would also help us as organizers avoid the hassle of money changing hands, bank accounts, and legal entities for this event.
Red Hat has already graciously provided a venue for free. I’d like to find a sponsor to provide pizza and soft drinks for lunch. If possible, I’d also like to find a sponsor to print some stickers.
By keeping this event lean, we win both ways. If COVID-19 is no longer an issue by June, then we get to lead a truly unique type of Python regional conference. If COVID-19 is still a problem, then we can easily postpone the event without much loss or pain.
The Next Steps
I’ve shared this idea with a few friends (including Calvin), and everyone so far agrees that this is a good path forward. In the coming days, we will share this plan to make sure the community agrees. Then, if this is the way, we can launch a very simple website, set up ticketing, and find someone to sponsor pizza.
Personally, I feel good about this idea. It’s a big relief to downsize. Deep down, I know I can trust the Python community to make this unique type of conference a hit.
Don’t understand my Chinese? Don’t feel bad – I don’t know much Mandarin, either! My wife and her mom are from China. When I developed a Django app to help my wife run her small business, I needed to translate the whole site into Chinese so that Mama could use it, too. Thankfully, Django’s translation framework is top-notch.
“East Meets West When Translating Django Apps” is the talk I gave about translating my family’s Django app between English and Chinese. For me, this talk had all the feels. I shared my family’s story as a backdrop. I showed Python code for each step in the translation workflow. I gave advice on my lessons learned. And I spoke truth to power – that translations should bring us all together.
PyOhio 2019 was one of my favorite conferences, ever. It was my ninth Python conference and my second PyOhio conference. There were so many good things that happened in such short time that, even three weeks later, I’m still processing everything. Here are my reflections on this outstanding conference.
PyOhio 2019 was held in Columbus, Ohio at the Ohio State Union. I really wanted to go because PyOhio 2018 was such a good time, and I started asking my friends in North Carolina if anyone wanted to join me. My friends Rick and Justin all emphatically replied YES! To make traveling more fun, we decided to turn it into a road trip! We dubbed ourselves the “PyCarolinas delegation”, piled into my Chrysler 300, and made the 8-hour drive in good time. Our friend Greg also joined us at PyOhio, though he traveled separately with his wife.
This was the first time I ever did a road trip to a conference. I’m so glad we did it. I felt like I got to spend great quality time with my friends. Many parts of the drive were quite scenic. We also discovered a Beef Jerky Outlet!
At PyOhio 2019, I delivered the holy trifecta of speaking opportunities: a talk, a tutorial, and a lightning talk. I felt both honored and humbled to be chosen for all three.
My talk was entitled Surviving Without Python. I talked about how we can use Python’s principles, projects, and people to inspire us even when we don’t use Python to solve our problems:
My tutorial was entitled Hands-On Web UI Testing. Python’s popularity continues to rise, and many people use it for testing. In my tutorial, I showed how you can develop a simple yet powerful solution with Python, pytest, and Selenium WebDriver to automate Web UI tests. The tutorial project in GitHub contains the code, instructions, and slides.
My lightning talk was announcing PyCarolinas 2020. My friend Calvin and I are teaming up to bring PyCarolinas back! We are targeting June 2020 in Raleigh, NC. Please help us make it happen!
There were so many great talks at PyOhio. Here were a few highlights.
Sprints are a Python conference event in which people work together on open-source projects. Conferences are the perfect time to have sprints because people are both co-located and excited. PyOhio 2019 was actually the first time I attended sprints. There were sprints on both Friday and Saturday nights. Accenture graciously hosted both sprints in their swanky office and provided refreshments.
I went to the sprints both nights with the honest intention to work on stuff. However, I spent the whole time socializing with friends. It was nevertheless time well spent! Many of us went to Jeni’s Splendid Ice Creams after the final sprint, too.
The PyOhio 2019 logo was lit! I joked that I was going to the conference just to get that logo sticker and t-shirt. Some other cool takeaways were the Numerator puzzles and the JP Morgan Chase puzzle blocks.
My sticker game is strong:
My backpack was also a hit!
Food and Drink
I had some good eats while in Columbus. My friend Mason recommended Raising Cane’s, which turned out to be awesome! So many people followed us there, too.
I also hopped an electric scooter to get bubble tea. Those scooters are so much fun. I hadn’t ridden one since PyTexas 2019! (Or maybe PyCon 2019; I don’t remember precisely.)
To relive PyOhio 2018 memories, I went to Eden Burger for a Vegan brunch on Sunday morning with friends! It was delicious and nutritious.
Our friend Greg recommended we visit Brewdog, a renowned Scottish craft brewery with a huge site on the outskirts of Columbus. We took the tour with the “beer school” course, and we stayed for a delicious dinner afterwards. So good, so very good. It was the best way to end the conference!
The best part about PyOhio 2019 was the time I spent with all my friends. I wish I could name everyone here, but there are just too many names. The Python community is the best. Conference friends are real friends. Also, for what it’s worth, they’ve given me the nickname “Pandy.”
My PyOhio 2019 experience can be summarized in one line:
Truth – I went all-in from leaving my house on Friday morning until returning Monday evening. The conference high is very real. My hope is that I’ll get to attend more great conferences like this, and also that I’ll be able to help make PyCarolinas as good as PyOhio!
Speaking at conferences is a great way for tech professionals to meet others, share their stuff, and travel to new places. It’s hard but rewarding work for speakers. I’ve been fortunate to have many speaking opportunities in the past few years. However, there is a hot-button issue in the speakership world: the “pay-to-speak” controversy. I’d like to offer my perspective on the matter.
What is Pay-To-Speak?
Have you ever wondered how speaking at conferences works? Conference organizers announce a “call-for-proposals” several weeks before the conference date. Potential speakers submit their proposals for talks, which often include an elevator pitch, an outline with time estimates, and personal information. Organizers will then invite the speakers with the best proposals to the conference.
Now, here’s the big question: Who covers the speaker’s costs? Conference travel isn’t free. Speakers will need transportation, a hotel room, meals, and other incidentals. Many speakers will also need to take time off from their day jobs to attend the conference. Some conferences will generously pay for their speakers’ travel-related expenses, either through reimbursements or a stipend. However, others are “pay-to-speak,” for which conferences do not cover any speaker travel costs. Speakers must ask their employers to sponsor them or, in the worst case, pay out of pocket. (For clarity, pay-to-speak does not mean that a speaker must pay the conference a fee for the privilege of speaking, at least not that I have seen.)
The pay-to-speak model can cause serious problems:
It can devalue the hard work speakers do to deliver captivating talks. Speakers essentially work for someone else without getting paid. They take several hours away from regular work and family time.
It can cause tension between speakers and their employers. A speaker will probably ask their manager to give both time off and travel reimbursement. That can be a tough conversation. It might involve office politics. Not every employer is thrilled to send their people to expensive conferences.
It can put a financial burden on speakers. If an employer won’t cover costs, then the speaker must pay out of pocket, which could force the speaker to make hard sacrifices.
Less-privileged speakers may need to decline invitations because they cannot afford to pay the travel costs themselves. That’s tragic and unfair.
These are real problems. As a result, many popular speakers boycott pay-to-speak conferences. Some conferences proudly advertise that they are not pay-to-speak. I won’t copy any hot tweets here, but just follow the #PayToSpeak hashtag on Twitter to see some. There are some strong words out there.
An Alternative Perspective
Personally, I love conferences that can cover my travel costs when I’m a speaker. It certainly eases my financial burden. I also think that for-profit conferences should not only cover speaker travel costs but also pay speakers for their presentations. However, the pay-to-speak model is not inherently evil. There are situations for which pay-to-speak is, in my opinion, a good model for conferences. Look no further than the Python conferences.
Python is one of the world’s most popular programming languages right now. Python is unique among programming languages because it is developed and supported entirely by the community. It is free, open-source software. The Python core developers, the people who “make” the language, are all volunteers. The Python Software Foundation (PSF) is a non-profit organization that holds the intellectual rights to Python. Python does not have a company behind it like Java (Oracle), C# (Microsoft), Go (Google), or Swift (Apple). Companies certainly support Python development and events, and a few individuals are employed by such efforts, but Python is nevertheless an independent, not-for-profit endeavor.
The best way to engage the Python community is through Python conferences. The biggest one is PyCon, held annually at different locations in North America. There are several other PyCons throughout the world, and the United States has many “regional” Python conferences like PyOhio and PyGotham. I’ve attended quite a few in recent years.
All the Python conferences I know are pay-to-speak. However, they are also non-profit. There’s no company making money off the conferences. The organizers are volunteers. Everything is financed through ticket sales, corporate sponsorships, and donations. The PSF also gives support. PyCon’s very tagline is, “By the community, for the community.”
Furthermore, Python conferences deliberately seek to keep registration prices low so that the conferences can be accessible to as many people as possible. That means costs must be kept low. Any conference needs money to run – lots of money. Speaker travel is a huge financial cost for a conference. Do the math: if a conference has 50 speakers, and each speaker needs about $2,000 for travel expenses, then the total cost is about $100,000! That’s enough to make any volunteer organizer lose sleep. Choosing a pay-to-speak model helps keep costs low.
As a result, registration prices for Python conferences are very affordable. Below are individual rates for 2019 conferences:
PyCon 2019: $400
DjangoCon 2019: $595
PyColorado 2019: $125
PyGotham 2019: $150
PyOhio 2019: free
Alternatively, there are for-profit conferences that charge thousands of dollars for their tickets.
Many Python conferences also offer financial aid grants to speakers and attendees who need assistance covering travel and registration costs. If an accepted speaker cannot afford to come on their own, they can probably get assistance. Many Python conferences also stagger ticket costs between educational, individual, and corporate tiers so that individuals paying out of pocket have less burden that those whose companies cover their costs. Simply put, if you want to go to a Python conference near you, then cost should not be a barrier.
Personally, I have no problem with Python’s pay-to-speak conferences. When I speak at Python conferences, I treat it as my service to the community – much like how others contribute code to open-source projects. The Python community has given much more to me than I could pay back, so instead, I’m happy to pay it forward. And the ones who “profit” from Python conferences are ultimately the ones who attend.
The pay-to-speak controversy is a complex issue. No side offers a perfect solution. What’s right or wrong is not the pay-to-speak model itself but rather the intention behind the decision to be pay-to-speak. If a conference seeks to profit from a speaker’s labor, then the speaker should be paid as with any business transaction. However, if a conference is truly a non-profit endeavor with benevolent intentions and a genuine inclusion strategy, then pay-to-speak might be okay.
When I was a kid, I was an enthusiastic Boy Scout. And every year, I looked forward to summer camp. For one full week, I would have a mini-adventure in the woods with my friends while earning new ranks and developing new skills. Summer camp was the highlight of every summer. As an adult, this is exactly how I feel about PyCon.
PyCon 2019 was my second time at PyCon. While I doubt any conference will ever have the same impact on me as my first PyCon, my second one was nevertheless every bit as good. I had a phenomenal experience. As always, I like to capture my reflections in an article so that I never forget the wonderful times I had. Here’s my story.
PyCon 2018 was a career-changing experience for me. I felt it at the time, and I can validate it now a year later. PyCon 2018 was my first serious engagement with the Python community. PyCon 2018 inspired me to speak at other conferences. PyCon 2018 introduced me to friends I still have today. As soon as PyCon 2018 ended, I knew that I needed to return for PyCon 2019.
Between 2018 and 2019, PrecisionLender (my employer) started doing much more Python work, especially in our data analytics division. I got approval from my manager to go to PyCon, but I also knew that others in the data division would benefit from PyCon as well. When I suggested the idea to the VP, he replied with one line: “Let’s do this thing!” With his blessing, I convinced four other PrecisionLender-ers to join me: Adam, Henry, Joe, and Raff.
I’m so thankful PrecisionLender approved our trips. Going with other friends from my company boosted not only my excitement for the conference but also my desire to learn new things. I’m proud to represent a company that supports its employees so well.
Good conferences are good but exhausting. They cram hundreds of adrenalized people into back-to-back activities requiring deep focus for hours at a time and for consecutive days. Amidst the mania, it is crucial to pace oneself. My friend Kojo sums this up perfectly in what he calls the “self care sprint.” It’s okay to step back to catch your breath. It’s vital to one’s mental health to take breaks, rest, and recover, especially at conferences as intense as PyCon.
Heeding Kojo’s advice, I took a #SelfCareSprint on the day before PyCon tutorials began. How so? I spent my afternoon at the Cleveland Museum of Art, which exhibits pieces from around the world dating from ancient times through the present day. Make no mistake: the Cleveland Museum of Art is world-class. In addition to their permanent collections, they had a special exhibit on Shinto artifacts from Japan. I barely had enough time to walk through all the galleries. What I did see impressed me, inspired me, and challenged me. Some pieces even spoke deeply to my soul.
The dichotomy of art and technology balance each other. Exploring pieces of art and the viewpoints they represent helped me center myself. I could clear my mind in preparation for the conference. I gained rest and recovery. I am human, after all.
PyCon 2019 hosted two days of tutorials before the main conference. Whereas talks are thirty minutes long and open to anyone, tutorials are three-hour sessions that require preregistration for limited seats. Tutorials are meant for hand-on learning with expert instructors. I had never attended tutorials at a conference before, and so this time, I wanted to try.
My first tutorial was Writing About Python (Even When You Hate Writing) by Thursday Bram. Since I do lots of blogging (and I ultimately want to write a book), I wanted to get first-hand advice on technical writing in the Python ecosystem. Thursday gave great advice on writing techniques and gotchas. The most valuable takeaway was her proofreading checklist. Her tutorial also inspired me to do something cool later in the conference. (Keep reading!)
My second tutorial was To trust or test? Automated testing of scientific projects with pytest. Unfortunately, this tutorial wasn’t right for me. I thought it would be about testing within data science, but it turned out to be a basic walkthrough of pytest. I didn’t learn any new material. What I did learn, though, was that I should be pickier with tutorials – I had to pay in advance, and I couldn’t just walk out to another talk.
My third tutorial was Escape from auto-manual testing with Hypothesis! by Zac Hatfield-Dodds. Hypothesis, a property-based testing tool, is hot right now. I first learned about it at the previous year’s PyCon, and I always wanted to learn more. Zac provided not only helpful lectures but a rigorous set of examples for us to complete. Hypothesis also works seamlessly with pytest. Zac made be a believer: Hypothesis is awesome! I need to spend more time learning it on my own.
As always, the talks were on point. I didn’t attend as many talks this year because I was too busy in the “hallway track,” but there were quite a few noteworthy ones that I attended.
In Don’t be a robot, build the bot, Mariatta showed how she and the Python core developers automated their GitHub workflow with the help of useful bots. It was cool to see how mundane processes can be automated away and how much more efficient teams can become.
In Break the Cycle: Three excellent Python tools to automate repetitive tasks, Thea Flowers showed how to use tox, nox, and Invoke to automate just about anything in Python. I’ll definitely refer back to this talk for testing.
In ¡Escuincla babosa!: Creating a telenovela script in three Python deep learning frameworks, Lorena Mesa showed us how serious machine learning can also be used for fun projects. Although the telenovela script she generated was short and humorous, it clearly proved that ML can get the job done.
In Scraping a Million Pokemon Battles: Distributed Systems By Example, Duy Nguyen showed how he scraped data from competitive Pokémon battles to level the playing field for new players. In the process, he developed a pretty slick distributed systems setup!
In Shipping your first Python package and automating future publishing, Chris Wilcox showed best practices on building and releasing Python packages. This talk was well-timed for me – I’ll definitely use this info for a current pet project of mine.
Dependency hell: a library author’s guide by Yanhui Li and Brian Quinlan will also be a great resource when considering dependencies for packages.
In to GIL or not to GIL: the Future of Multi-Core (C)Python, Eric Snow showed his thoughts for how to fix problems with the GIL and true multi-core processing.
In The Perils of Inheritance: Why We Should Prefer Composition, Ariel Ortiz made clear the nasty side effects inheritance can have and how composition is often a much better approach. The talk was fairly introductory, but I couldn’t agree more.
The expo hall was full of companies and organizations. The swankiest booths this year were:
Capital One – the Guido portrait and puzzle and the Zen of Python wall
Jetbrains – content developer tables for PyBites, Real Python, and others
Microsoft – four interactive Azure stations + active lab tables
However, my favorite company in the expo hall, hands down, was The Pokémon Company International. Their table was small and easily overlooked, but every time I passed by, it was packed. Everyone loves Pokémon! I got to meet a few of their engineers and managers. Apparently, they do much of their backend in Python. They’re also growing quite a lot. They were raffling off a giant Pikachu, and one of the engineers even developed a Google Home app that would make Pikachu respond whenever someone spoke to it! It was so charming to see them there. I’m glad that things are going well for Pokémon.
If you don’t overfill your swag bag, then you’re doing PyCon wrong. This year’s haul was as good as last year’s. I walked away with:
A deck of cards with the Zen of Python from Capital One
An artistic deck of playing cards from Heroku
16 packs of Pokémon cards
A JetBrains yo-yo
A few pairs of sunglasses
Water bottles from DoorDash, Wayfair, and Citadel
A guide to building Slack apps
The best t-shirt award goes to Microsoft for their Visual Studio Code shirt, with honorable mentions for LinkedIn and SmartBear. I also shared a good amount of this swag with my coworkers at PrecisionLender.
Cleveland (and greater Ohio) are renowned for craft breweries. Every time I return to Ohio, I’m always delighted by the beers I discover. I spent many lunches and dinners with a flight set on the side. Here’s where I went:
Hofbräuhaus Cleveland, twice! (I even bought the souvenir Maßkrug!)
Masthead Brewing Company
Noble Beast Brewing Company
Southern Tier Brewing Company
Great Lakes Brewing Company
The best was the Lichtenhainer from Noble Beast – a sour that tasted like a ham sandwich on sourdough. The worst was the “shampoo beer” from Southern Tier – did they forget to rinse the lines after cleaning them?
Back at PyCon 2018, I met an Aussie by the name of Julian Sequeira, co-founder of PyBites. We hit it off. In fact, meeting Julian is one of the reasons why I continue to engage the Python community today. Through Julian, I met other friends like Jason Wattier, Brian Okken, Cristian Medina, and many others. Leading up to PyCon 2019, Julian organized a BIG dinner at Great Lakes Brewing Company for a bunch of Python content developers: PyBites, Real Python, Python Bytes, Test & Code, tryexceptpass, and Automation Panda (me!). Not only was it a time of sweet reunion, but I finally got to meet others like Bob Belderbos, Michael Kennedy, and David Amos in person. One of the best parts of the dinner was when a few of us chose to walk back to the hotels over the bridge instead of calling taxis. The night was cold, but the experience was worth every second.
Sadly, I did not get to deliver a full talk or tutorial at PyCon 2019. Believe me, I submitted. But that didn’t stop me from trying – there’s always one more chance with lightning talks! One exercise during the Writing About Python tutorial was to pitch a lightning talk idea. At the time, I struggled to come up with a good topic. I first considered something about testing or being a tester, but those ideas just didn’t feel right. Then, I struck gold: what about giving helpful tips for blogging, based on my experiences with Automation Panda?
I put my idea on the call-for-lightning-talk-proposals on Saturday morning: “3 Quick Tips for Software Blogging.” When I didn’t receive any notification by lunchtime, I thought my pitch had been rejected. Then, while chilling in the quiet room at 3pm, I received an email: “Congrats! You’re giving your lightning talk today at 5pm!” Excitement, then panic, took over. I threw some slides together, rehearsed them in my head, and marched myself to the main auditorium. My lightning talk was second in queue, and I delivered it like a BOSS!
Ever since my first PyCon, I’ve dreamed about having a Python conference in the Carolinas. There was a PyCarolinas 2012 and a PyData Carolinas 2016, but both were one-hit wonders. My dream remained in my back pocket until PyCon 2019.
While meandering the expo hall on Friday, I ran into Tim Hopper and Brian Corbin, two friends who were also from the Carolinas. We talked about lots of things, but one point of discussion was about relaunching PyCarolinas. Later, Dustin Ingram, chair of PyTexas, tweeted that there would be a conference organizer’s open space on Saturday. I asked if I could join because of my PyCarolinas dreams, and he said absolutely yes. Brian and I both attended, made connections, and got tons of helpful information.
Dustin then asked me if I’d like to include a slide for PyCarolinas in the “regional conference parade” on Sunday morning after the lightning talks. Heck yeah! PyCarolinas was the very last slide as a call-to-action: We have a dream; come help us make it real!
At 10am on Sunday, I held an open space to talk about (re)launching PyCarolinas. 26 people came! We got everyone’s info, created a Slack room, and started throwing around ideas. In the week after the conference, over a hundred people signed up for our Slack room. The excitement is palpable. Our goal is to host PyCarolinas in summer of 2020 for 150+ people. I’m so thankful I got the opportunity to be the spark that lit this wildfire, on such a big stage.
Together with my blog, I use my Twitter handle @AutomationPanda for professional development. Twitter is especially helpful during conferences for communicating with friends and sharing experiences. During PyCon 2019, I crossed a big milestone: I hit over 1000 followers! That was cool.
I also made my first viral tweet, thanks to a sticker from Facebook:
If you read these reflections down this far, thank you. Seriously, I mean it.
The best part about PyCon 2019 for me was the time I spent with my friends.
PyCon 2019 was a high point for friendships. Everyone I knew was there. I couldn’t walk for 10 minutes around the convention center without running into someone I knew. I feel like I’m truly part of the Python community now. Here were just a few highlights:
Going there with my PL team: Adam, Henry, Joe, and Raff.
German dinner and souvenir Maßkrugs with Adam at Hofbräuhaus.
“Shampoo” beer with Joe and Adam at Southern Tier.
Snagging Pokémon cards on opening night with Mason Egger, and then running into Jason Wattier on the way.
Ramen dinner and Hilton rooftop drinks with the PL crew plus Mason.
Impromptu lunch with Adrienne so she could share the awesome things she’s accomplishing.
PyCon Canada 2018 was my fourth and final Python conference of 2018. I proposed a talk on a whim after seeing the CFP on Twitter. What the heck, why not? It couldn’t hurt to try. Much to my surprise (and delight), I was accepted to speak! So, up to the Great White North I went for the first time since childhood.
#PyConCA2018 took place in Toronto, Ontario from November 10-13 at the Chestnut Residence downtown. I attended the conference (Nov 10-11) but skipped out on the sprints (Nov 12-13). It looked like about 400-500 people attended the conference, but I don’t know the exact count. A few vendors had tables with swag, but the talks were clearly the main focus of the conference.
PyConCA offered three tracks for talks plus a tutorials track. There were two time slot lengths for talks: 10 minutes and 30 minutes. I had not attended a conference with short 10-minute talks before, but they turned out to be a great way to cover a broader range of topics in a short amount of time. The tutorials were long-running sessions for which anyone could register at no additional charge, but they each had a limited number of seats. (I regret not signing up in advance for the Kubernetes tutorial.) There were also four decent keynote addresses.
I spent a lot of time reworking the slides, writing new example code, and rehearsing my words before the talk. And I felt great when I presented it: without any script, I hit all the major points without skipping a beat and ended right on time. I felt my passion flow through me as I spoke. This tweet pretty much summed up my feelings:
Meeting people is one of my favorite parts of Python conferences. Everyone is friendly. Everyone will chat with you. Everyone will get excited about whatever makes you excited. This time around, I ended up in a posse with a few other guys who mostly attended the same talks and also sat at the same lunch table. I hope our paths cross again. I also got to meet Elaine Wong, the conference chair.
After the Conference
I was on my own for both evenings after the conference talks. My Airbnb rental was just two blocks away in Chinatown, so I could walk to and from the conference center (in the bitter Toronto cold). On Saturday night, I ate a delicious dry hotpot of beef, lotus flowers, and wood ear mushrooms at the House of Gourmet, followed by a fancy bubble tea in a light-bulb-shaped glass across the street at Royaltea. On Sunday night, I treated myself to foot-and-body massage at Evergreen Beauty and Wellness. My therapist, who was from Beijing, helped me practice my Mandarin. Thereafter, I went to Sichuanren for an all-you-can-eat hotpot buffet: beef, pork, lamb, seafood, and veggies. It’s so much fun to visit a big city with a large Chinatown – it provides access to things I can’t always get at home. That US-to-Canadian-dollar exchange rate is quite favorable, too. The only challenges I faced were (a) no mobile phone service and (b) worrying if establishments would accept my credit/debit cards. The temps also hovered around freezing.
PyConCA was a strong finish for my 2018 conferences. I’m so thankful for my opportunity to speak, and I’m glad that I took the time to attend.
My favorite physical takeaway items of swag were:
My PyConCA sticker, now proudly displayed on my Macbook
My PyConCA t-shirt, which will soon appear in my rotation
My PyConCA “toque” (Canadian word for “knit winter cap with a pom-pom on top”)
My main inspirational takeaway from this conference could be summed up in one word: confidence. I feel much more confident in myself as a conference speaker after nailing my talk this fourth time. After listening to a number of talks, I also feel much more confident in my Python web development skills. Picking up Flask (which is on my todo list) should be doable. Finally, I feel capable of learning data science and AI with Python when the time comes. Many talks showed how machine learning can solve novel problems with straightforward tools and techniques.
That should conclude this panda’s round of conferences for the year. I look forward to what 2019 brings!