Selenium + unittest
Add visual regression testing to your existing Selenium + unittest suite. The witness(driver, name) helper integrates with Python's standard unittest.TestCase pattern.
Prerequisitesโ
- Python 3.8+
- Chrome browser
seleniuminstalled
pip install selenium
1. Install the CLIโ
npm install -g @testivai/witness-cdp
The CLI is a Node.js tool. Node.js 18+ is required even for Python projects.
2. Run the Setup Wizardโ
npx testivai init
Select when prompted:
? Select your language: โบ Python
? Select your test framework: โบ Selenium (unittest)
? Where are your test files? โบ tests
The wizard generates two files:
| File | Purpose |
|---|---|
testivai_witness.py | witness(driver, name) helper function |
tests/test_visual_example.py | Working example test using unittest.TestCase |
3. Authenticateโ
npx testivai auth <your-api-key>
Get your API key from the TestivAI Dashboard.
4. Chrome Setupโ
Add --remote-debugging-port=9222 to your setUp method:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import unittest
class VisualTest(unittest.TestCase):
def setUp(self):
options = Options()
options.add_argument('--remote-debugging-port=9222')
self.driver = webdriver.Chrome(options=options)
def tearDown(self):
self.driver.quit()
5. Add Capture Callsโ
Import witness from the generated helper and call it in your test methods:
from testivai_witness import witness
class VisualTest(unittest.TestCase):
def test_homepage(self):
self.driver.get('http://localhost:3000')
witness(self.driver, 'homepage')
def test_login_page(self):
self.driver.get('http://localhost:3000/login')
witness(self.driver, 'login-page')
The generated helper file (testivai_witness.py):
# TestivAI Visual Regression Helper
def witness(driver, name):
"""Capture a visual snapshot."""
return driver.execute_script(f"return window.testivaiWitness('{name}')")
6. Full Working Exampleโ
The wizard generates this example at tests/test_visual_example.py:
# TestivAI Visual Regression Example
import unittest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from testivai_witness import witness
class VisualTest(unittest.TestCase):
def setUp(self):
options = Options()
options.add_argument('--remote-debugging-port=9222')
self.driver = webdriver.Chrome(options=options)
def tearDown(self):
self.driver.quit()
def test_homepage(self):
self.driver.get('http://localhost:3000')
witness(self.driver, 'homepage')
if __name__ == '__main__':
unittest.main()
7. Runโ
testivai run "python -m unittest discover tests/"
Or run a specific test file:
testivai run "python -m unittest tests/test_visual_example.py"
setUpClass patternโ
For a shared driver across all methods in a class (faster, one Chrome instance):
class VisualTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
options = Options()
options.add_argument('--remote-debugging-port=9222')
cls.driver = webdriver.Chrome(options=options)
@classmethod
def tearDownClass(cls):
cls.driver.quit()
CI/CDโ
Add headless Chrome args for CI:
options.add_argument('--remote-debugging-port=9222')
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
GitHub Actions example:
- name: Run visual tests
run: testivai run "python -m unittest discover tests/"
env:
TESTIVAI_API_KEY: ${{ secrets.TESTIVAI_API_KEY }}
How it worksโ
witness(driver, name) calls driver.execute_script() to invoke window.testivaiWitness(name) โ the global function injected by the CDP SDK. The SDK captures a full 5-layer snapshot and uploads it for analysis.