Select Page
πŸ•’ Reading Time: 3 minutes

Below I composed a list of tips and gotchas from more then 5 years of experience in test automation, Clean Code and PEP8. The list is not structured and contains both Python specific advices as well as general ideas. All the points only represent author’s humble opinion and should be taken at your own rist. Please note that this is not AI generated articleπŸ˜‰ although ChatGPT helped with HTML formatting and proofreading.

Variables

Local Variables

Local variables should have descriptive names in lower_snake_case. Use explicit words whenever possible. Avoid using abbreviations or mind mapping, except for extremely common terms like x (x-coordinate), or env (environment).

# ❌ Poor
num = 0
current_t = 0

# βœ… Better
number_of_retries = 0
current_time = 0

Constants

Python does not have built-in constants. To signal that a variable should be treated as constant (read-only), use UPPER_SNAKE_CASE.

# βœ… Constant convention
TIMEOUT = 60

Underscore

Underscores can be used to avoid conflicts with reserved keywords or other variables. A single underscore ( _ ) is also a common convention to indicate a throwaway value.

# βœ… Throwaway variable in loop
for _ in range(10):
    some_action_to_repeat()

Functions

Functions should have descriptive names that convey their purpose without needing to read the code or documentation. Type hinting is strongly encouraged.

# ❌ Poor
def f(): ...
def search(s): ...

# βœ… Better
def find_user_by_name(name: str) -> Optional[User]: ...

Boolean Return Values

Function names returning boolean should start with is_.

# ❌ Poor
def element_present(): ...

# βœ… Better
def is_element_present(): ...

Private Functions

Prefix function names with an underscore to indicate they are intended for internal use only.

# ❌ Poor
def this_function_private(): ...

# βœ… Better
def _this_function_private(): ...

Assignments

Tuple Assignment

Use tuple unpacking for functions returning multiple values.

# ❌ Poor
dimensions = retrieve_dimensions()
length = dimensions[0]
width = dimensions[1]
height = dimensions[2]

# βœ… Better
length, width, height = retrieve_dimensions()

Conditional Operators

Ternary Operator

Python supports conditional expressions for inline ternary logic:

# βœ… Preferred
result = value1 if condition else value2

# 😐 Acceptable but less safe (can be buggy in some cases)
result = value1 and condition or value2

Nested Ifs

Try to avoid deep nesting. Use guard clauses instead.

# ❌ Poor
if condition1:
    if condition2:
        if condition3:
            ...

# βœ… Better
if not condition1:
    return

Simplifying Boolean Returns

# ❌ Poor
if condition:
    return True
return False

# βœ… Better
return condition

Avoid Negative Clauses in Function Names

When naming functions that return booleans, prefer positive phrasing. This improves readability and avoids the cognitive overhead of double negatives.

# ❌ Poor
if is_not_user_logged_in():

# βœ… Better
if not is_user_logged_in():

Loops

Comprehensions

Use list comprehensions when appropriate for clarity and conciseness.

Timeout Loop

# ❌ Poor
while tries < timeout:
    # condition to exit
    time.sleep(1)
    tries += 1

# βœ… Better
start = datetime.now()
while (datetime.now() - start).seconds < timeout:
    # condition to exit
    time.sleep(1)

Functions: Developer Mindset

While unit testing for automation code may not be enforced (comparing to production code), writing testable code and thinking in terms of testability can improve maintainability and quality.

Function Should Do One Thing

Watch out for red flags:

  • Long functions
  • Complex logic
  • Repeated logic

Try to Limit Parameters

Fewer parameters usually lead to simpler, easier to test and more reusable functions.

Returning Boolean

# ❌ Poor
def some_function(self):
    if is_element_present() and is_element_enabled():
        return True
    else:
        return False

# βœ… Better
def some_function(self):
    return is_element_present() and is_element_enabled()

Comments

Make sure to include comments when necessary, however keep in mind that clean self-descriptive code does not require comments.

General Advices

Reinventing the Wheel

Avoid reinventing existing functionality. If you think what you’re creating may already exist in Python built-in, 3rd party or internal libraries search for ready made solution first.

Types

Type Checking

# ❌ Poor
if type(variable) == list:

# βœ… Better
if isinstance(variable, list):

Why:

class A: pass
class B: pass
b = B()

type(b) == A     # False
isinstance(b, A) # True

Comparing with Singletons

# ❌ Poor
if x == None:
if x == True:
if x == False:

# βœ… Better
if x is None:
if x is True:
if x:
if x is False:
if not x:

Data Structures

Comprehensions

Use comprehensions for short, readable logic.

# ❌ Poor
double_array = []
for i in array:
    double_array.append(i**2)

# βœ… Better
double_array = [i**2 for i in array]

No Need for Indexes

# ❌ Poor
for i in range(len(array)):
    print(array[i])

# βœ… Better
for element in array:
    print(element)

# βœ… If you do need the index
for i, element in enumerate(array):
    print(f"index={i} element={element}")

Conclusion

Keep these tips in mind next time you are writing automated tests, to keep them clean, maintainable and robust. As with all ‘best’ practices, take them with a grain of salt. Rules are created to violate them, so next time when reality hits and you need to create function with 15 parameters, think about it twice and do ya thing.

I’m bad, and that’s good. I will never be good, and that’s not bad. There’s no one I’d rather be than me.
-Ralph Wreck-it-Ralph

Engineer80lvl

I am a former aerospace engineer turned web development enthusiast with a passion for exploring the digital landscape. My interests include SEO, automation, and web scraping, where I enjoy finding innovative ways to optimize and enhance online experiences. Beyond the world of technology, I have a love for finance, chess, and playing the piano. In my free time, you can find me swimming, hiking, or diving into the latest video games. Always eager to learn and grow, I enjoy blending my technical skills with my diverse hobbies to keep life exciting and fulfilling.

Pin It on Pinterest

Share This