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!
On August 14, 2019, I teamed up with SmartBear to deliver a one-hour webinar about Web UI testing with Python! It was an honor to work with Nicholas Brown, Digital Marketing Manager for CrossBrowserTesting at SmartBear Software, to make this webinar happen.
In the webinar, I showed how to build a basic Web UI test automation solution using Python, pytest, and Selenium WebDriver. The tutorial covered automating one test, a simple DuckDuckGo search, from inception to automation. It also showed how to use CrossBrowserTesting to scale the solution so that it can run tests on any browser, any platform, and any version in the cloud as a service!
I encourage you to clone the Github repository and try to run the example test on your own! Make sure to get a CrossBrowserTesting trial license so you can try different browsers. You can also try to write new tests of your own. All instructions are in the README. Have fun with it!
After the tutorial, we took questions from the audience. Here are answers to the top questions:
How can we automate UI interactions for CAPTCHA?
CAPTCHA is a feature many websites use to determine whether or not a user is human. Most CAPTCHAs require the user to read obscured text from an image, but there are other variations. By their very nature, CAPTCHAs are designed to thwart UI automation.
When someone asked this question during the webinar, I didn’t have an answer, so I did some research afterwards. Unfortunately, it looks like there’s no easy solution. The best workarounds involve driving apps through their APIs to avoid CAPTCHAs. I also saw some services that offer to solve CAPTCHAs.
Are there any standard Page Object Pattern implementations in Python?
Not really. Mozilla maintains the PyPOM project, but I personally haven’t used it. I like to keep my page objects pretty simple, as shown in the tutorial. I also recommend the Screenplay Pattern, which handles concerns better as test automation solutions grow larger. I’m actually working on a Pythonic implementation of the Screenplay Pattern that I hope to release soon!
How can I run Python tests that use Selenium WebDriver and pytest from Jenkins?
Any major Continuous Integration tool like Jenkins can easily run Web UI tests in any major language. First, make sure the nodes are properly configured to run the tests – they’ll need Python with the appropriate packages. If you plan to use local browsers, make sure the nodes have the browsers and WebDriver executables properly installed. If you plan to use remote browsers (like with CrossBrowserTesting), make sure your CI environment can call out to the remote service. Test jobs can simply call pytest from the command line to launch the tests. I also recommend the “JUnit” pytest option to generate a JUnit-style XML test report because most CI tools require that format for displaying and tracking test results.
How can I combine API and database testing with Web UI testing?
One way to handle API and database testing is to write integration tests separate from Web UI tests. You can still use pytest, but you’d use a library like requests for APIs andSQLAlchemy for databases.
Another approach is to write “hybrid” tests that use APIs and database calls to help Web UI testing. Browsers are notoriously slow compared to direct back-end calls. For example, database calls could pre-populate data so that, upon login, the website already displays stuff to test. Hybrid tests can make tests much faster and much safer.
How can we test mobile apps and browsers using Python?
Even though our tutorial covered desktop-based browser UI interactions, the strategy for testing mobile apps and browsers is the same. Mobile tests need Appium, which is like a special version of WebDriver for mobile features. The Page Object Pattern (or Screenplay Pattern) still applies. CrossBrowserTesting provides mobile platforms, too!
Python is such a popular language for good reason: Its principles are strong. However, if Python is “the second-best language for everything”… that means the first-best is often chosen instead. Oh no! How can Pythonistas survive a project or workplace without our favorite language?
Personally, even though I love Python, I don’t use it daily at my full time job. Nevertheless, Pythonic thinking guides my whole approach to software. I will talk about how the things that make Python great can be applied to non-Python places in three primary ways:
Have you ever discovered a bug in a web app? Yuck! Almost everyone has. Bugs look bad, interrupt the user’s experience, and cheapen the web app’s value. Severe bugs can incur serious business costs and tarnish the provider’s reputation.
So, how can we prevent these bugs from reaching users? The best way to catch bugs is to test the web app. However, web UI testing can be difficult: it requires more effort than unit testing, and it has a bad rap for being flaky.
Never fear! Recently, I teamed up with the awesome folks at TestProject to develop a helpful tutorial that makes web UI test automation easy with the power of Python! The tutorial is named Web Testing Made Easy with Python, Pytest and Selenium WebDriver. It is available for free as a set of TestProject blog articles together with a GitHub example project.
In our tutorial, we will build a simple yet robust web UI test solution using Python, pytest, and Selenium WebDriver. We cover strategies for good test design as well as patterns for good automation code. By the end of the tutorial, you’ll be a web test automation champ! Your Python test project can be the foundation for your own test cases, too.
I personally want to thank TestProject for this collaboration. TestProject provides helpful tools that can supercharge your test automation. They offer a smart test recorder, a bunch of add-ons that act like test case building blocks, an SDK that can make test automation coding easier, and beautiful analytics to see exactly what the tests are doing. Not only is TestProject a cool platform, but the people with whom I’ve worked there are great. Be sure to check it out!
A Twitter friend recently asked me the following question:
I work in a Microsoft shop. We have 40 developers who use .NET (C#). We also have several manual testers and 5 automation engineers who developed our test automation solution in Python. However, our leadership wants to move everything completely to C#.
Would it be better to (a) train 40 .NET developers in Python to use the existing test solution or (b) train the testers in .NET and port the tests to C#?
This is a very tough question. It’s not as simple as asking for the best test automation language because there are people, positions, and solutions already in place. Honestly, I can’t give a conclusive answer without more context, but I can offer five points of advice.
What is the state of the Python test solution?
How big and how bad is the existing Python test automation solution? Rewriting tests that already work fine has low return-on-investment. However, rewriting tests that have problems like flakiness or false positives might be worthwhile. More tests means more time, too. Please read my article, Our Test Automation Has Problems. Should We Start Over?, to learn what problems would warrant a rewrite.
Why not have two test solutions?
If the existing Python tests are fine, then rewriting them is a huge opportunity cost. Instead of rewriting existing tests, developers and testers could spend their time writing only the new tests in a new C# solution. The Python solution would be “legacy” and would not have any new tests added to it. Old tests would disappear with deprecated features, too. Eventually, the C# tests would take over. The main drawback for this possibility is the continued maintenance of a Python stack.
Do the manual testers have any programming experience?
Many manual testers do not have strong programming skills. Some may not have any programming skills at all! They will have a big learning curve when training to do test automation. Python would be a much easier language for them to learn than C# because it is concise, readable, and friendly for beginners. Conversely, Python would be fairly easy for C# developers to learn as they go.
What advantages will conformity bring?
Retraining workers and rewriting code is no small task. From a business perspective, they are investment costs. There must be significant returns that outweigh the cost of the transition. Make sure those returns are known and real.
Will developers also automate tests?
Many teams choose to write their test automation code in the same language as the product code so that developers can more easily automate tests. However, in my experience, developers typically don’t write many tests, especially when others on the team are dedicated testers. Test automation is difficult and has unique challenges. Some developers have bad attitudes about testing, too. Changing the language probably won’t change the deeper issues.
The decision to choose between C# and Python for test automation is very personal for me. I faced this choice directly when I started working at PrecisionLender. Even though I deeply love Python, we chose to use C#. It was the right choice: we were a Microsoft shop with no test solution (yet) and no Python stack in place. My team and I have no regrets.
There is nothing with test automation that either language can’t do. Both are solid choices. The best choice for a team depends more upon the team’s situation than differences between these languages.
To see my webinar recording, register here. Definitely watch the previous webinar first.
Just like last time, attendees asks several great questions that we simply could not answer live. I categorized all questions we received and answered them below. Please note that some questions might be rephrased or combined with others.
In a typical Agile development process, who should write feature files?
The Three Amigos! Product owners, developers, and testers should all come together to figure out behaviors. I recommend doing Example Mapping to formulate before writing Gherkin scenarios. The green example cards should be turned into feature files. The specific person who writes the feature files is up to team preference. It could be a collaborative effort, or it could be divided-and-conquered. Any one of the Three Amigos can do it.
How can we apply BDD to SAFe (Scaled Agile Framework) teams?
BDD practices like Three Amigos meetings, Example Mapping, Behavior Specification with Gherkin, and Behavior Implementation can become part of any process. All of these practices happen at the level of the development teams. Teams could even share Gherkin steps and test frameworks wherever sharing makes sense. Check out BDD 101: Behavior-Driven Agile.
What advice can you give to teams that use BDD tests frameworks solely as an automation tool and not part of a greater BDD process?
Do the best with what you’ve got. Try to show how other BDD practices can pragmatically improve your team’s development and delivery work. See also:
What is the difference between a scenario and a scenario outline?
A scenario is a procedure of Given-When-Then steps that covers one example for one behavior. If there are any parameters for steps, then a scenario has exactly one combination of possible inputs. A scenario outline is a Given-When-Then procedure that can have multiple examples of one behavior provided as a table of input combos. Each input row will run the same steps once, just with different parameter inputs. See BDD 101: Gherkin by Example to see examples.
What do you think about long tables in scenarios?
Long tables in Gherkin usually look terrible. They’re hard to read, and they create a wall of text. They may also include unnecessary variations. Stick to the Unique Example rule.
Are Given steps mandatory, or can scenarios start directly with When steps?
None of the step types are mandatory. It is valid to write a scenario that skips the Given and has only When-Then steps. It is also valid to write scenarios that are Given-Then or Given-When. In fact, it is syntactically valid to put steps in any order. However, I strongly recommend keeping Given-When-Then step order to properly frame behaviors.
Are quotation marks required for parameters?
No, quotation marks are not required for parameters, but they are a popular convention, and one that I recommend. Quotes make parameters easy to identify.
Questions about Gherkin Scenarios
How do we make sure each scenario focuses on an individual, independent behavior?
Do Example Mapping first as a team. Write scenarios together, or review them with others. Ask, “What makes this behavior unique?” Make sure to use strict Given-When-Then step order when defining the behavior. Rethink the scenario if it is more than 10 lines long. Look out for unnecessary complication.
What does it mean for a scenario to be “chronological”?
Scenario steps should be written as if they were on a timeline. Each step will be executed after the previous one, so its description must start where the previous one ended. Remember, steps will be automated as if they were scripts.
How do we write a very low-level scenario without having a wall of text?
Don’t write low-level scenarios! Gherkin is best for feature testing, not unit testing. Steps should focus on intention and business value. Instead of writing “type, type, click, wait,” write “log into the app.” If you absolutely must write a low-level scenario, remember that the same principles apply. Be intuitively descriptive. Focus on individual behaviors. Keep scenarios concise.
If all scenarios in a feature file have only one user, is it okay to use first-person perspective instead of third-person?
In my opinion, no. I favor third-person perspective universally. Trying to limit usage to one feature file won’t work because any step can be used by any feature file within a test project. The entire solution must be either first-person or third-person. There’s no middle ground.
Can we write Gherkin scenarios with personas?
Yes! Personas can make scenarios more meaningful and understandable. Make sure to define the personas well – they could be described under the Feature section or in a separate text file.
How do we write Gherkin scenarios that need to validate lots of information on a page?
Pick the most important pieces of information to check. You could write separate Then steps for each assertion, or you could push small-but-similar validations down to the automation level to avoid Gherkin clutter.
How do we write Gherkin scenarios for validating Web UI fields?
Typically, I treat each field validation as an independent behavior, and thus I write separate scenarios to check each field. If the scenario steps simply enter a textual value and verify a specific message, then I might make a Scenario Outline with example rows for each equivalence class of inputs.
How do we write Gherkin scenarios that have multiple inputs and setup steps? (Example: an API with ten parameters)
Gherkin allows multiple steps of the same type to be written using “And” and “But” keywords. It’s not a problem to have “Given-And-And” or “When-And-And”. If you discover that different scenarios repeat the same setup steps, then I recommend either moving those common steps to a Background section or writing a new step that covers multiple calls (for conciseness).
One example from the webinar showed searching for shoes and adding them to a shopping cart as part of one scenario. Aren’t those two different behaviors?
Here’s the scenario in question:
Scenario: Add shoes to the shopping cart
Given the ShoeStore home page is displayed
When the shopper searches for “red pumps”
And the shopper adds the first result to the cart
Then the cart has one pair of “red pumps”
We could have split this scenario into two. I just chose to define the behavior this way. This scenario is a bit more end-to-end because it covers a basic but typical workflow. It may also have leveraged existing steps, which expedites automation development. Overall, the scenario is still concise, chronological, and intuitively understandable. Remember, there is an art as well as a science to writing good Gherkin.
Questions about Automation
Do scenarios need to be independent of each other?
Yes, unequivocally. Tests that are not independent could interfere with each other and cause unexpected failures. Independence also reinforces singular behavioral focus.
How do we start a scenario “in media res” without it depending on other tests?
At the Gherkin level, write Given steps that define a new starting point for the behavior. For example, many teams develop Web apps. It’s common to think that the starting point for all tests is login. However, the starting point can be a few pages after login.
At the automation level, it may be useful to implement the Given steps by calling other steps. For example, if a Given step should start at a user’s profile page, then perhaps it could internally call the login step and the click-the-profile-link step. Test steps may repetitively do the same operations for different tests, but test case independence will be preserved, and unique failures will be reported.
What is the best way to handle preconditions like logging into a Web app?
The simplest way to handle preconditions is to write Given steps. If those Given steps are shared by all scenarios in a feature file, then move them to a Background section. Automation hooks can also perform common setup and cleanup actions, depending upon the test framework. Personally, I prefer to use hooks to do automatic login rather than repeat Given steps for many scenarios.
Is it better to set up and tear down new test objects for each test case, or is it better to use shared, pre-created objects?
That depends upon the object. Most objects like WebDrivers and page objects should have scenario scope, meaning they are created fresh for each scenario and then torn down when the scenario ends. The only time an object should be shared across scenarios is if it is immutable or very expensive to create. For example, configuration data could be read in once before all tests and then injected immutably into each scenario. The safe position is always to use fresh objects; justify why sharing is needed before trying it.
I want to use Serenity for BDD and testing. Should I use Cucumber-like Gherkin feature files, or should I use Serenity’s native methods?
If a company already has a large BDD test solution that is poorly implemented, would it be better to keep it going or try to change it?
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.
Web UI tests with Selenium WebDriver must interact with elements on a Web page. Locating elements can be tricky because expected elements may or may not be on the page. Furthermore, WebDriver might not be able to interact with some elements that exist on the page. That may seem crazy, but let’s understand why.
Web UI interactions universally follow these steps:
Wait for an element to be ready.
Get the element using a locator (ID, CSS selector, XPath, etc.).
Send commands (like clicking or typing) or queries (like getting text) to the element.
Clearly, an element must be “ready” before interactions can happen. As humans, we intuitively define “ready” as, “The page is loaded, and the element is visible.” Automation code is a bit more technical because there are two different ways to define readiness:
Existence: the element exists in the HTML structure of the page.
Appearance: the element exists and it is visible on the page.
Existence can easily be determined by WebDriver’s “find elements” method. The plural “find elements” method will return a list of all elements matching a locator query. If no elements match the locator, then an empty list is returned. The singular “find element” method, on the other hand, will return the first element matching the locator or throw an exception if no elements are found. Thus, the plural version is more convenient to use for checking existence.
Here’s an example existence method in C#:
public bool Exists(IWebDriver driver, By locator) =>
driver.FindElements(locator).Count > 0;
Checking for existence is the most basic level of readiness. If an element doesn’t exist, interactions with it simply cannot happen. However, existence alone may not be sufficient for interactions. Selenium WebDriver requires elements to not only exist but also to be displayed for interactions like sending clicks and scraping text. Existing elements may be scrolled out of view or even deliberately hidden. WebDriver calls to such elements will yield cryptic exceptions. That’s why waiting for appearance is usually the better readiness condition.
Here’s an example appearance method in C#:
// Assume that the locator targets one element, not multiple
public bool Appears(IWebDriver driver, By locator) =>
Exists(driver, locator) && driver.FindElement(locator).Displayed;
Existence must be checked first, or else the “Displayed” call will throw an exception whenever existence is false.
Putting it all together, here’s what a button click interaction could look like in C#:
// Assume this is a method in a Page Object class
// Assume that "Driver" is the WebDriver instance
public void ClickThatButton()
var button = By.Id("that-button");
var wait = new WebDriverWait(Driver, new System.Timespan(0, 0, 15));
wait.Until((driver) => Appears(driver, button));
It’s good practice to make explicit waits before locating and using elements. It’s also good practice to get fresh elements for every interaction call in order to avoid pesky stale element exceptions. Calls like these should be placed in Page Object methods or Screenplay Pattern tasks and questions so that interactions are safe and thorough.
Appearance may not always be the right choice. There may be times when a test should check if an element doesn’t exist or if an element exists but is hidden. Just think before you code.
My wife and I have been proud Airbnb hosts since 2018. We currently host three guest suites between two properties in North Carolina, and we love doing it. Airbnb enables us to take care of my wife’s mom and afford critical house renovations. Overall, hosting has been a worthwhile, albeit sometimes tiring, experience.
Between our three listings, we see many guests. We try to be “super” hosts to every guest who stays with us, and most of our guests likewise try to be super guests. However, nobody is perfect. While we believe that the vast majority of Airbnb users want to be good, not everyone may be cognizant of irksome or even damaging missteps. From our perspective as hosts, we’d like to share 12 ways for good guests to be truly great guests.
#1. Share information about yourself and your travel plans.
As hosts, we don’t know who you are. You are strangers who we meet online, and you want to stay at our house. We want to trust you, but help us! Don’t be shy. Update your Airbnb profile with your email, phone number, and information about yourself. Share your actual profile picture – not a picture of your kids or some dumb cartoon sketch. Upload a copy of your government ID. When you request to stay at our place, share why you are traveling. Tell us when you plan to arrive and leave, and tell us exactly who all the guests will be. Ask us for local recommendations.
The more you share about yourselves, the more likely we will be as hosts to accept your request to stay. Conversely, we have also rejected requests when guests don’t upload their IDs or when they aren’t forthright with information.
#2. Read (and follow) all house rules and guides.
When guests request to stay at a listing, they must agree to follow all house rules (in addition to Airbnb’s policies). House rules are attached to the listing and accessible before booking. Our house rules are pretty basic, but we frequently see the following violated:
No shoes inside.
Park on the street, not in the driveway.
Quiet hours after 10pm.
Breaking these rules is not a huge problem but unfortunately reveals guests to be careless and disrespectful. Read the rules before you book.
Similarly, read the guides before you check in. We provide a full step-by-step guide with pictures for each listing, including the entry codes. We also provide WiFi and Netflix information. Asking us for the combo code or trying to enter the wrong door reveals that guests did not prepare.
#3. No means no.
Hosts set rules for reasons. Guests should not expect exceptions. For example, we do not allow children under age 12 in any of our listings because they are not baby-proof or child-proof. We have fragile decorations, furniture with sharp edges, and outlets without safety covers. We also do not allow pets because I am allergic to animal dander. These rules are published clearly on our listings. Please do not request to stay with us if you intend to bring a child or a dog. Please do not ask for an exception because “he’s a good boy.” Or worse, don’t show up with a rule violation and put your host in an awkward situation. It’s okay to ask for things that are unclear or unspecified, but please be reasonable with requests, and do not be offended if the host says no.
#4. Include all guests in the booking.
Each listing has a maximum number of allowed guests. When guests book a listing, they must include how many people will come. Guests should list all people, but unfortunately that doesn’t always happen. It’s common for a guest to book for one person and then have more show up. This may or may not be a serious problem. For example, one of our suites can accommodate 3 people, but we charge extra per night because we need to turn a futon into a bed. We’ve had guests book it for one person and then have three show up – creating an awkward situation. We also had one problematic guest invite five or six others over without even asking. As a guest, just make sure to include all members of your party in the booking, and ask for permission before bringing over someone not in the booking.
#5. Cancel early (when necessary).
Cancellations are always disappointing for hosts, but we understand that plans change. If you as a guest need to cancel your reservation, then please cancel as soon as possible. Every day you hold a reservation is an opportunity cost for someone else to book. When a guest cancels late, the host loses the income and has little chance to find a replacement.
Furthermore, respect the host’s cancellation policy. Hosts choose one of Airbnb’s standard policies, so make sure to check the listing when you book. If you cancel too late and don’t get a full refund from Airbnb, then please don’t feel entitled to get a full refund directly from the host.
#6. Treat the space well.
As hosts, we put a lot of work into making our guest suites nice. We carefully choose the furniture and decor. We clean the suites thoroughly between stays and inspect them for any problems. And we tend to cycle through many guests in short time. Our guest suites need to “survive” day to day.
As guests, please take care of the spaces you rent. Be careful not to cause any damages. Clean up your messes. Wash your dishes. Hang up your towels. Don’t leave food out for bugs. Overall, just think about how you’d want a guest to treat your home.
#7. When in doubt, ask for permission.
Grace Hopper once said, “It is easier to ask forgiveness than it is to get permission.” However, this is terrible advice for Airbnb rentals! Guests should always ask their hosts whenever the rules or guides are unclear. My wife and I are fairly accommodating with most requests, such as late checkin or storing food in our fridge. We just don’t like surprises – like someone unexpectedly cooking during our family mealtimes.
#8. Don’t do sketchy things.
Airbnb stays are meant to be a fun, safe experience for both guests and hosts. There should be an implicit sense of trust between guest and host. Neither party should participate in illegal or discomforting activities. Drugs, sex work, and pornography are unwelcome – and not to mention a violation of Airbnb’s policies. If you are a guest, don’t do these things. My wife and I have kicked out guests for doing sketchy things.
Also, be clear and open about your intentions, especially if they are atypical. If you need to stay up late to work on a project, let your host know so they don’t wonder why your lights are on all night. If you need to bring large medical hardware, let your host know so they don’t think you’re “Breaking Bad.” If you want to use the listing for a family photo shoot, let your host know so they don’t suspect you of filming porn. Remember, you are staying in another person’s space. Please don’t make them worry.
#9. Be patient when problems happen.
Problems happen. Even though hosts work really hard to make things perfect, sometimes they overlook details, and other times things are out of their control. Our guest suites have had problems with temperature, hot water, burned-out light bulbs, and even bugs.
As guests, please be gracious with problems. Tell your host right away. Good hosts will want to fix the problems ASAP. Share pictures so your host can see exactly what is wrong. Be polite, not belligerent or whiny. Please be patient while the host works to fix the problems. And don’t wait until the final review to share a problem. By then, it’s too late. Guest shouldn’t suffer and hosts shouldn’t get bad reviews when problems can be fixed.
#10. Be honest when you cause problems.
Again, problems happen. Here’s a few we’ve seen:
Guests parked in the driveway and blocked our cars.
Guests tracked mud into the house.
Guests spilled coffee on the bedroom carpet.
Good hosts will focus on solutions rather than blame. As guests, please take responsibility for any problems you cause and help work toward solutions. Be quick to respond to your host, and be willing to pay the host for any damages. For example, the guest who spilled the coffee reimbursed us about $10 for carpet cleaner.
#11. Check out on time.
Good listings have high occupancy rates. All three of our suites are typically 75-100% occupied every month. Whenever a guest checks out, a new guest will probably check in later that same day. As hosts, we need to flip the space in that short window between checkout and checkin. That includes inspecting, vacuuming, cleaning, laundry, remaking the bed, and handling any surprises.
Please make sure to check out punctually. Tell your host ahead of time when you plan to check out, and send the host a message to let them know when you leave.
On a related note: the most common request from our guests is for an early checkin time. We try to accommodate early checkin for guests who ask, but we cannot make guarantees. An early checkin time depends directly upon the previous guests’ checkout time.
#12. Don’t leave poor reviews for poor reasons.
At the end of a stay, the host and the guest review each other. Reviews are kept private until either both parties submit them or 14 days pass. The bidirectional nature of reviews holds guests and hosts equally accountable to each other, which encourages better behavior from both sides.
I encourage everyone – guests and hosts alike – to give truthful, transparent reviews. A robust review system keeps the Airbnb platform trustworthy. At the same time, be mindful about what you write in your reviews. Hosts rely upon good reviews for income, and bad reviews – even 4 stars instead of 5 – can be especially damaging. If you leave a bad review, make sure it is for a good reason. Nothing is more frustrating than to see reviews like these:
A guest said everything during their weekend stay was absolutely perfect. They adored the location, the decor, and the coffee machine. They said they’d definitely come back. No negative comments. 4 stars instead of 5.
A guest gave 3 stars for accuracy because the guest suite didn’t have a private entry, even though the listing explicitly stated that there was no private entry.
A guest complained that one of the bedsheets was upside down and not tucked in perfectly.
Thankfully, off-the-mark reviews like these happen rarely. I’m sure some hosts are guilty as well. Please don’t give poor reviews for poor reasons.
There are many more things we could share, but the “golden rule” comes down to this: Be a good guest to every host, just as much as you want your host to be good to every guest. Even if your host is lousy, still strive to be a good guest for your integrity and the integrity of other Airbnb users.
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.