Checkbox, dropdown and radio button controls are present in almost every enterprise web application.
Checkbox
Used when users can select one or more independent options.
Multiple choicesDropdown
Used to select a value such as country, department, category or status.
SelectionRadio Button
Used when the user should select one option from a group.
Single choice
Playwright provides dedicated APIs for checkbox controls:
check(), uncheck() and
is_checked().
terms = page.get_by_label(
"I agree to the Terms and Conditions"
)
terms.check()
terms.uncheck()
check() communicates the intention clearly:
the test wants the checkbox to be checked.
After checking a checkbox, validate the state when that state is important to the business workflow.
from playwright.sync_api import expect
terms = page.get_by_label(
"I agree to the Terms and Conditions"
)
terms.check()
expect(terms).to_be_checked()
❌ Avoid
assert terms.is_checked()This performs an immediate check rather than using Playwright's retrying assertion model.
✅ Preferred
expect(terms).to_be_checked()Web-first assertions wait and retry until the expected state is reached or the timeout is exceeded.
Imagine an online shopping checkout page containing:
- Terms and Conditions checkbox
- Marketing newsletter checkbox
- Gift wrapping checkbox
from playwright.sync_api import expect
terms = page.get_by_label(
"I agree to the Terms and Conditions"
)
newsletter = page.get_by_label(
"Subscribe to newsletter"
)
gift_wrap = page.get_by_label(
"Add gift wrapping"
)
terms.check()
newsletter.check()
gift_wrap.uncheck()
expect(terms).to_be_checked()
expect(newsletter).to_be_checked()
expect(gift_wrap).not_to_be_checked()
A permissions form is a common enterprise example where multiple checkboxes can be selected.
page.get_by_label(
"View Customers"
).check()
page.get_by_label(
"Create Customers"
).check()
page.get_by_label(
"Edit Customers"
).check()
page.get_by_label(
"Delete Customers"
).uncheck()
This is useful for admin portals, role management systems, employee permissions and access-control applications.
For a native HTML <select> element, Playwright
provides select_option().
page.get_by_label(
"Country"
).select_option("IN")
You can also select using the visible label.
page.get_by_label(
"Country"
).select_option(
label="India"
)
Consider a customer registration form containing Country, State and Customer Type.
page.get_by_label(
"Country"
).select_option(
label="India"
)
page.get_by_label(
"State"
).select_option(
label="Maharashtra"
)
page.get_by_label(
"Customer Type"
).select_option(
label="Premium"
)
After selecting an option, validate the selected state when it is part of the test's business purpose.
from playwright.sync_api import expect
country = page.get_by_label("Country")
country.select_option(
label="India"
)
expect(country).to_have_value("IN")
Not every dropdown is a native HTML <select>.
Modern applications often use custom dropdown components.
page.get_by_role(
"combobox",
name="Country"
).click()
page.get_by_role(
"option",
name="India"
).click()
select_option() for every
dropdown. First determine whether the application uses a native
HTML select or a custom component.
Radio buttons normally allow one selection from a group.
Playwright provides check() for radio buttons as well.
page.get_by_label(
"Credit Card"
).check()
Another example:
page.get_by_label(
"Standard Delivery"
).check()
An e-commerce checkout may offer several payment methods:
from playwright.sync_api import expect
page.get_by_label(
"Credit Card"
).check()
expect(
page.get_by_label("Credit Card")
).to_be_checked()
standard = page.get_by_label(
"Standard Delivery"
)
express = page.get_by_label(
"Express Delivery"
)
express.check()
expect(express).to_be_checked()
expect(standard).not_to_be_checked()
| Control | Typical Behavior | Playwright API | Example |
|---|---|---|---|
| Checkbox | Zero or more options can be selected | check() |
Terms, newsletter, permissions |
| Radio Button | Normally one option in a group | check() |
Payment method, gender, shipping type |
| Dropdown | Select one or more values depending on control | select_option() |
Country, department, category |
❌ Avoid When Better Locators Exist
page.locator(
"#checkout > div:nth-child(4) input"
).click()The selector depends on the DOM structure and can break when unrelated HTML changes are introduced.
✅ Preferred
page.get_by_label(
"I agree to the Terms and Conditions"
).check()The locator expresses the actual purpose of the control.
Do not use fixed delays after selecting a checkbox, radio button or dropdown option just because the application may update.
❌ Avoid
page.get_by_label(
"Express Delivery"
).check()
page.wait_for_timeout(3000)✅ Preferred
page.get_by_label(
"Express Delivery"
).check()
expect(
page.get_by_text(
"Express delivery selected"
)
).to_be_visible()This example combines all three controls in a realistic checkout workflow.
from playwright.sync_api import expect
def test_checkout_options(page):
page.goto(
"https://shop.example.test/checkout"
)
# Dropdown
country = page.get_by_label("Country")
country.select_option(
label="India"
)
expect(country).to_have_value("IN")
# Radio button
express = page.get_by_label(
"Express Delivery"
)
express.check()
expect(express).to_be_checked()
# Checkbox
terms = page.get_by_label(
"I agree to the Terms and Conditions"
)
terms.check()
expect(terms).to_be_checked()
# Submit
page.get_by_role(
"button",
name="Place Order"
).click()
# Business validation
expect(
page.get_by_text(
"Order placed successfully"
)
).to_be_visible()
Selenium can also handle checkboxes effectively. A common approach is to locate the element and click it.
from selenium.webdriver.common.by import By
terms = driver.find_element(
By.ID,
"terms"
)
terms.click()
Selenium can also inspect the state using
is_selected().
assert terms.is_selected()
For native select elements, Selenium commonly uses its
Select helper.
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
country = Select(
driver.find_element(
By.ID,
"country"
)
)
country.select_by_visible_text(
"India"
)
payment = driver.find_element(
By.ID,
"credit-card"
)
payment.click()
assert payment.is_selected()
| Scenario | Playwright | Selenium |
|---|---|---|
| Checkbox |
locator.check()
|
Locate element and commonly use click()
|
| Checkbox state |
expect(locator).to_be_checked()
|
element.is_selected()
|
| Radio button |
locator.check()
|
Locate and click()
|
| Radio state |
expect(locator).to_be_checked()
|
element.is_selected()
|
| Native dropdown |
select_option()
|
Select()
|
| Custom dropdown | Role/label based locator interactions | Locator + click/select interactions |
| Synchronization | Locator actions and web-first assertions provide automatic waiting behavior | Explicit waits are commonly used when application state requires synchronization |
| Assertions |
Built-in web-first expect() assertions
|
Usually combined with the selected test framework |
Scenario
Customer selects:
- Country = India
- Shipping = Express Delivery
- Terms = Checked
Playwright
page.get_by_label(
"Country"
).select_option(
label="India"
)
page.get_by_label(
"Express Delivery"
).check()
terms = page.get_by_label(
"I agree to the Terms and Conditions"
)
terms.check()
expect(terms).to_be_checked()Selenium
country = Select(
driver.find_element(
By.ID,
"country"
)
)
country.select_by_visible_text(
"India"
)
driver.find_element(
By.ID,
"express"
).click()
terms = driver.find_element(
By.ID,
"terms"
)
terms.click()
assert terms.is_selected()Dedicated Checkbox API
check() and uncheck() directly
express checkbox intent.
Accessible Locators
get_by_label() and
get_by_role() make form controls easier
to identify.
Web-First Assertions
State assertions retry until the expected state is reached or the timeout is exceeded.
Less Timing Code
Well-designed tests can avoid many fixed-delay synchronization workarounds.
Readable Tests
Business actions such as "select India" or "check Terms" are easy to understand.
Modern Applications
The locator and synchronization model is designed for modern dynamic web applications.
-
Prefer
get_by_label()for labeled form controls. -
Prefer
get_by_role()for accessible UI controls. -
Use
check()for checkboxes and radio buttons. -
Use
uncheck()when a checkbox should be disabled. -
Use
select_option()for native HTML select elements. - Understand whether a dropdown is native or custom.
- Validate selected states when they are important to the test.
- Use web-first assertions instead of immediate state assertions when synchronization matters.
- Avoid fixed waits after selection.
- Avoid brittle CSS/XPath selectors when semantic locators exist.
- Test the business result, not just the click.
- Keep test data deterministic.
Checkbox → check / uncheck
Dropdown → select_option for native select
Radio → check
Result → web-first assertion
Playwright and Selenium can both automate these controls. Playwright's dedicated locator APIs, accessible locator strategy, actionability checks and web-first assertions can make the resulting automation more expressive and reduce manual synchronization in many modern web applications.