പൈടെസ്റ്റിന്റെ മുഴുവൻ കഴിവുകളും അഡ്വാൻസ്ഡ് ഫിക്സ്ചർ ടെക്നിക്കുകളിലൂടെ പ്രയോജനപ്പെടുത്തുക. കാര്യക്ഷമമായ പൈത്തൺ ടെസ്റ്റിംഗിനായി പാരാമീറ്ററൈസ്ഡ് ടെസ്റ്റിംഗും മോക്ക് ഇന്റഗ്രേഷനും പഠിക്കുക.
പൈടെസ്റ്റ് അഡ്വാൻസ്ഡ് ഫിക്സ്ചറുകളിൽ വൈദഗ്ദ്ധ്യം നേടാം: പാരാമീറ്ററൈസ്ഡ് ടെസ്റ്റിംഗും മോക്ക് ഇന്റഗ്രേഷനും
പൈത്തണിനായുള്ള ശക്തവും വഴക്കമുള്ളതുമായ ഒരു ടെസ്റ്റിംഗ് ഫ്രെയിംവർക്കാണ് പൈടെസ്റ്റ്. അതിന്റെ ലാളിത്യവും വിപുലീകരിക്കാനുള്ള കഴിവും ലോകമെമ്പാടുമുള്ള ഡെവലപ്പർമാർക്കിടയിൽ ഇതിനെ പ്രിയപ്പെട്ടതാക്കുന്നു. പൈടെസ്റ്റിന്റെ ഏറ്റവും ആകർഷകമായ സവിശേഷതകളിലൊന്ന് അതിന്റെ ഫിക്സ്ചർ സിസ്റ്റമാണ്, ഇത് മികച്ചതും പുനരുപയോഗിക്കാവുന്നതുമായ ടെസ്റ്റ് സജ്ജീകരണങ്ങൾക്ക് വഴിയൊരുക്കുന്നു. ഈ ബ്ലോഗ് പോസ്റ്റ്, അഡ്വാൻസ്ഡ് ഫിക്സ്ചർ ടെക്നിക്കുകളിലേക്ക്, പ്രത്യേകിച്ച് പാരാമീറ്ററൈസ്ഡ് ടെസ്റ്റിംഗ്, മോക്ക് ഇന്റഗ്രേഷൻ എന്നിവയിൽ ശ്രദ്ധ കേന്ദ്രീകരിക്കുന്നു. ഈ ടെക്നിക്കുകൾ എങ്ങനെ നിങ്ങളുടെ ടെസ്റ്റിംഗ് വർക്ക്ഫ്ലോയെ കാര്യമായി മെച്ചപ്പെടുത്താമെന്നും, കൂടുതൽ കരുത്തുറ്റതും പരിപാലിക്കാൻ എളുപ്പമുള്ളതുമായ കോഡിലേക്ക് നയിക്കാമെന്നും നമ്മൾ പരിശോധിക്കും.
പൈടെസ്റ്റ് ഫിക്സ്ചറുകൾ മനസ്സിലാക്കാം
അഡ്വാൻസ്ഡ് വിഷയങ്ങളിലേക്ക് കടക്കുന്നതിന് മുമ്പ്, പൈടെസ്റ്റ് ഫിക്സ്ചറുകളുടെ അടിസ്ഥാനകാര്യങ്ങൾ ഹ്രസ്വമായി ഓർമ്മിക്കാം. ഒരു ഫിക്സ്ചർ എന്നത്, അത് പ്രയോഗിക്കുന്ന ഓരോ ടെസ്റ്റ് ഫംഗ്ഷനും മുമ്പായി പ്രവർത്തിക്കുന്ന ഒരു ഫംഗ്ഷനാണ്. ടെസ്റ്റുകൾക്ക് ഒരു നിശ്ചിത അടിസ്ഥാനം നൽകാനും, സ്ഥിരത ഉറപ്പാക്കാനും, ആവർത്തന സ്വഭാവമുള്ള കോഡുകൾ കുറയ്ക്കാനും ഇത് ഉപയോഗിക്കുന്നു. ഫിക്സ്ചറുകൾക്ക് ഇനിപ്പറയുന്നതുപോലുള്ള ജോലികൾ ചെയ്യാൻ കഴിയും:
- ഡാറ്റാബേസ് കണക്ഷൻ സജ്ജീകരിക്കുന്നു
- താൽക്കാലിക ഫയലുകളോ ഡയറക്ടറികളോ ഉണ്ടാക്കുന്നു
- നിർദ്ദിഷ്ട കോൺഫിഗറേഷനുകളുള്ള ഒബ്ജക്റ്റുകളെ സജ്ജമാക്കുന്നു
- ഒരു എപിഐ (API) ഉപയോഗിച്ച് ഓതന്റിക്കേറ്റ് ചെയ്യുന്നു
ഫിക്സ്ചറുകൾ കോഡിന്റെ പുനരുപയോഗം പ്രോത്സാഹിപ്പിക്കുകയും നിങ്ങളുടെ ടെസ്റ്റുകൾ കൂടുതൽ വായിക്കാൻ എളുപ്പമുള്ളതും പരിപാലിക്കാൻ സാധിക്കുന്നതുമാക്കുകയും ചെയ്യുന്നു. അവയുടെ ലൈഫ്ടൈമും റിസോഴ്സ് ഉപയോഗവും നിയന്ത്രിക്കുന്നതിനായി വ്യത്യസ്ത സ്കോപ്പുകളിൽ (ഫംഗ്ഷൻ, മൊഡ്യൂൾ, സെഷൻ) അവയെ നിർവചിക്കാൻ സാധിക്കും.
അടിസ്ഥാന ഫിക്സ്ചർ ഉദാഹരണം
ഒരു താൽക്കാലിക ഡയറക്ടറി ഉണ്ടാക്കുന്ന ഒരു ലളിതമായ പൈടെസ്റ്റ് ഫിക്സ്ചറിന്റെ ഉദാഹരണം താഴെ നൽകുന്നു:
import pytest
import tempfile
import os
@pytest.fixture
def temp_dir():
with tempfile.TemporaryDirectory() as tmpdir:
yield tmpdir
ഈ ഫിക്സ്ചർ ഒരു ടെസ്റ്റിൽ ഉപയോഗിക്കുന്നതിന്, നിങ്ങളുടെ ടെസ്റ്റ് ഫംഗ്ഷന്റെ ഒരു ആർഗ്യുമെന്റായി അതിനെ ഉൾപ്പെടുത്തിയാൽ മതി:
def test_create_file(temp_dir):
filepath = os.path.join(temp_dir, "test_file.txt")
with open(filepath, "w") as f:
f.write("Hello, world!")
assert os.path.exists(filepath)
പൈടെസ്റ്റ് ഉപയോഗിച്ചുള്ള പാരാമീറ്ററൈസ്ഡ് ടെസ്റ്റിംഗ്
ഒരേ ടെസ്റ്റ് ഫംഗ്ഷൻ വ്യത്യസ്ത ഇൻപുട്ട് ഡാറ്റകൾ ഉപയോഗിച്ച് ഒന്നിലധികം തവണ പ്രവർത്തിപ്പിക്കാൻ പാരാമീറ്ററൈസ്ഡ് ടെസ്റ്റിംഗ് നിങ്ങളെ അനുവദിക്കുന്നു. വ്യത്യസ്ത ഇൻപുട്ടുകളും പ്രതീക്ഷിക്കുന്ന ഔട്ട്പുട്ടുകളുമുള്ള ഫംഗ്ഷനുകൾ പരീക്ഷിക്കുന്നതിന് ഇത് വളരെ ഉപയോഗപ്രദമാണ്. പാരാമീറ്ററൈസ്ഡ് ടെസ്റ്റുകൾ നടപ്പിലാക്കുന്നതിനായി പൈടെസ്റ്റ് @pytest.mark.parametrize ഡെക്കറേറ്റർ നൽകുന്നു.
പാരാമീറ്ററൈസ്ഡ് ടെസ്റ്റിംഗിന്റെ പ്രയോജനങ്ങൾ
- കോഡിന്റെ ആവർത്തനം കുറയ്ക്കുന്നു: ഏതാണ്ട് ഒരുപോലെയുള്ള ഒന്നിലധികം ടെസ്റ്റ് ഫംഗ്ഷനുകൾ എഴുതുന്നത് ഒഴിവാക്കുക.
- ടെസ്റ്റ് കവറേജ് മെച്ചപ്പെടുത്തുന്നു: വൈവിധ്യമാർന്ന ഇൻപുട്ട് മൂല്യങ്ങൾ എളുപ്പത്തിൽ പരീക്ഷിക്കുക.
- ടെസ്റ്റിന്റെ വായനാക്ഷമത വർദ്ധിപ്പിക്കുന്നു: ഓരോ ടെസ്റ്റ് കേസിനും വേണ്ടിയുള്ള ഇൻപുട്ട് മൂല്യങ്ങളും പ്രതീക്ഷിക്കുന്ന ഔട്ട്പുട്ടുകളും വ്യക്തമായി നിർവചിക്കുക.
അടിസ്ഥാന പാരാമീറ്ററൈസേഷൻ ഉദാഹരണം
രണ്ട് സംഖ്യകൾ കൂട്ടുന്ന ഒരു ഫംഗ്ഷൻ നിങ്ങൾക്കുണ്ടെന്ന് കരുതുക:
def add(x, y):
return x + y
വ്യത്യസ്ത ഇൻപുട്ട് മൂല്യങ്ങൾ ഉപയോഗിച്ച് ഈ ഫംഗ്ഷൻ പരീക്ഷിക്കുന്നതിന് നിങ്ങൾക്ക് പാരാമീറ്ററൈസ്ഡ് ടെസ്റ്റിംഗ് ഉപയോഗിക്കാം:
import pytest
@pytest.mark.parametrize("x, y, expected", [
(1, 2, 3),
(5, 5, 10),
(-1, 1, 0),
(0, 0, 0),
])
def test_add(x, y, expected):
assert add(x, y) == expected
ഈ ഉദാഹരണത്തിൽ, @pytest.mark.parametrize ഡെക്കറേറ്റർ നാല് ടെസ്റ്റ് കേസുകൾ നിർവചിക്കുന്നു, ഓരോന്നിനും x, y, കൂടാതെ പ്രതീക്ഷിക്കുന്ന ഫലം എന്നിവയ്ക്കായി വ്യത്യസ്ത മൂല്യങ്ങളുണ്ട്. പൈടെസ്റ്റ് test_add ഫംഗ്ഷൻ നാല് തവണ പ്രവർത്തിപ്പിക്കും, ഓരോ പാരാമീറ്റർ സെറ്റിനും ഓരോ തവണ വീതം.
അഡ്വാൻസ്ഡ് പാരാമീറ്ററൈസേഷൻ ടെക്നിക്കുകൾ
പാരാമീറ്ററൈസേഷനായി പൈടെസ്റ്റ് നിരവധി അഡ്വാൻസ്ഡ് ടെക്നിക്കുകൾ വാഗ്ദാനം ചെയ്യുന്നു, അവയിൽ ഉൾപ്പെടുന്നവ:
- ഫിക്സ്ചറുകൾ പാരാമീറ്ററൈസേഷനോടൊപ്പം ഉപയോഗിക്കുന്നത്: ഓരോ ടെസ്റ്റ് കേസിനും വ്യത്യസ്ത സജ്ജീകരണങ്ങൾ നൽകുന്നതിന് ഫിക്സ്ചറുകളെ പാരാമീറ്ററൈസേഷനുമായി സംയോജിപ്പിക്കുക.
- ടെസ്റ്റ് കേസുകൾക്കുള്ള ഐഡികൾ (Ids): മികച്ച റിപ്പോർട്ടിംഗിനും ഡീബഗ്ഗിംഗിനുമായി ടെസ്റ്റ് കേസുകൾക്ക് കസ്റ്റം ഐഡികൾ നൽകുക.
- ഇൻഡയറക്ട് പാരാമീറ്ററൈസേഷൻ: ഫിക്സ്ചറുകളിലേക്ക് കൈമാറുന്ന ആർഗ്യുമെന്റുകളെ പാരാമീറ്ററൈസ് ചെയ്യുക, ഇത് ഡൈനാമിക് ഫിക്സ്ചർ നിർമ്മാണത്തിന് അനുവദിക്കുന്നു.
പാരാമീറ്ററൈസേഷനോടൊപ്പം ഫിക്സ്ചറുകൾ ഉപയോഗിക്കുന്നത്
ടെസ്റ്റിലേക്ക് കൈമാറുന്ന പാരാമീറ്ററുകളെ അടിസ്ഥാനമാക്കി ഫിക്സ്ചറുകൾ ഡൈനാമിക്കായി കോൺഫിഗർ ചെയ്യാൻ ഇത് നിങ്ങളെ അനുവദിക്കുന്നു. ഒരു ഡാറ്റാബേസുമായി സംവദിക്കുന്ന ഒരു ഫംഗ്ഷൻ നിങ്ങൾ പരീക്ഷിക്കുകയാണെന്ന് കരുതുക. വ്യത്യസ്ത ടെസ്റ്റ് കേസുകൾക്കായി നിങ്ങൾക്ക് വ്യത്യസ്ത ഡാറ്റാബേസ് കോൺഫിഗറേഷനുകൾ (ഉദാഹരണത്തിന്, വ്യത്യസ്ത കണക്ഷൻ സ്ട്രിംഗുകൾ) ഉപയോഗിക്കാൻ താൽപ്പര്യമുണ്ടാകാം.
import pytest
@pytest.fixture
def db_config(request):
if request.param == "prod":
return {"host": "prod.example.com", "port": 5432}
elif request.param == "test":
return {"host": "test.example.com", "port": 5433}
else:
raise ValueError("Invalid database environment")
@pytest.fixture
def db_connection(db_config):
# Simulate establishing a database connection
print(f"Connecting to database at {db_config['host']}:{db_config['port']}")
return f"Connection to {db_config['host']}"
@pytest.mark.parametrize("db_config", ["prod", "test"], indirect=True)
def test_database_interaction(db_connection):
# Your test logic here, using the db_connection fixture
print(f"Using connection: {db_connection}")
assert "Connection" in db_connection
ഈ ഉദാഹരണത്തിൽ, db_config ഫിക്സ്ചർ പാരാമീറ്ററൈസ് ചെയ്തിരിക്കുന്നു. indirect=True എന്ന ആർഗ്യുമെന്റ്, പാരാമീറ്ററുകളായ "prod", "test" എന്നിവ db_config ഫിക്സ്ചർ ഫംഗ്ഷനിലേക്ക് കൈമാറാൻ പൈടെസ്റ്റിനോട് പറയുന്നു. തുടർന്ന് db_config ഫിക്സ്ചർ പാരാമീറ്റർ മൂല്യത്തെ അടിസ്ഥാനമാക്കി വ്യത്യസ്ത ഡാറ്റാബേസ് കോൺഫിഗറേഷനുകൾ നൽകുന്നു. db_connection ഫിക്സ്ചർ ഒരു ഡാറ്റാബേസ് കണക്ഷൻ സ്ഥാപിക്കാൻ db_config ഫിക്സ്ചർ ഉപയോഗിക്കുന്നു. അവസാനമായി, test_database_interaction ഫംഗ്ഷൻ ഡാറ്റാബേസുമായി സംവദിക്കാൻ db_connection ഫിക്സ്ചർ ഉപയോഗിക്കുന്നു.
ടെസ്റ്റ് കേസുകൾക്കുള്ള ഐഡികൾ (Ids)
കസ്റ്റം ഐഡികൾ നിങ്ങളുടെ ടെസ്റ്റ് റിപ്പോർട്ടിലെ ടെസ്റ്റ് കേസുകൾക്ക് കൂടുതൽ വിവരണാത്മകമായ പേരുകൾ നൽകുന്നു, ഇത് പരാജയങ്ങൾ തിരിച്ചറിയാനും ഡീബഗ് ചെയ്യാനും എളുപ്പമാക്കുന്നു.
import pytest
@pytest.mark.parametrize(
"input_string, expected_output",
[
("hello", "HELLO"),
("world", "WORLD"),
("", ""),
],
ids=["lowercase_hello", "lowercase_world", "empty_string"],
)
def test_uppercase(input_string, expected_output):
assert input_string.upper() == expected_output
ഐഡികൾ ഇല്ലാതെ, പൈടെസ്റ്റ് test_uppercase[0], test_uppercase[1] എന്നിങ്ങനെയുള്ള സാധാരണ പേരുകൾ സൃഷ്ടിക്കും. ഐഡികൾ ഉപയോഗിക്കുമ്പോൾ, ടെസ്റ്റ് റിപ്പോർട്ട് test_uppercase[lowercase_hello] പോലുള്ള കൂടുതൽ അർത്ഥവത്തായ പേരുകൾ പ്രദർശിപ്പിക്കും.
ഇൻഡയറക്ട് പാരാമീറ്ററൈസേഷൻ
ടെസ്റ്റ് ഫംഗ്ഷനെ നേരിട്ട് പാരാമീറ്ററൈസ് ചെയ്യുന്നതിന് പകരം ഒരു ഫിക്സ്ചറിലേക്കുള്ള ഇൻപുട്ടിനെ പാരാമീറ്ററൈസ് ചെയ്യാൻ ഇൻഡയറക്ട് പാരാമീറ്ററൈസേഷൻ നിങ്ങളെ അനുവദിക്കുന്നു. പാരാമീറ്റർ മൂല്യത്തെ അടിസ്ഥാനമാക്കി വ്യത്യസ്ത ഫിക്സ്ചർ ഇൻസ്റ്റൻസുകൾ ഉണ്ടാക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുമ്പോൾ ഇത് സഹായകമാണ്.
import pytest
@pytest.fixture
def input_data(request):
if request.param == "valid":
return {"name": "John Doe", "email": "john.doe@example.com"}
elif request.param == "invalid":
return {"name": "", "email": "invalid-email"}
else:
raise ValueError("Invalid input data type")
def validate_data(data):
if not data["name"]:
return False, "Name cannot be empty"
if "@" not in data["email"]:
return False, "Invalid email address"
return True, "Valid data"
@pytest.mark.parametrize("input_data", ["valid", "invalid"], indirect=True)
def test_validate_data(input_data):
is_valid, message = validate_data(input_data)
if input_data == {"name": "John Doe", "email": "john.doe@example.com"}:
assert is_valid is True
assert message == "Valid data"
else:
assert is_valid is False
assert message in ["Name cannot be empty", "Invalid email address"]
ഈ ഉദാഹരണത്തിൽ, input_data ഫിക്സ്ചർ "valid", "invalid" എന്നീ മൂല്യങ്ങൾ ഉപയോഗിച്ച് പാരാമീറ്ററൈസ് ചെയ്തിരിക്കുന്നു. indirect=True എന്ന ആർഗ്യുമെന്റ് ഈ മൂല്യങ്ങൾ input_data ഫിക്സ്ചർ ഫംഗ്ഷനിലേക്ക് കൈമാറാൻ പൈടെസ്റ്റിനോട് പറയുന്നു. തുടർന്ന് input_data ഫിക്സ്ചർ പാരാമീറ്റർ മൂല്യത്തെ അടിസ്ഥാനമാക്കി വ്യത്യസ്ത ഡാറ്റാ ഡിക്ഷണറികൾ നൽകുന്നു. test_validate_data ഫംഗ്ഷൻ വ്യത്യസ്ത ഇൻപുട്ട് ഡാറ്റ ഉപയോഗിച്ച് validate_data ഫംഗ്ഷൻ പരീക്ഷിക്കാൻ input_data ഫിക്സ്ചർ ഉപയോഗിക്കുന്നു.
പൈടെസ്റ്റ് ഉപയോഗിച്ചുള്ള മോക്കിംഗ്
ടെസ്റ്റിംഗ് സമയത്ത് യഥാർത്ഥ ഡിപൻഡൻസികളെ നിയന്ത്രിത പകരക്കാർ (മോക്കുകൾ) ഉപയോഗിച്ച് മാറ്റിസ്ഥാപിക്കുന്ന ഒരു ടെക്നിക്കാണ് മോക്കിംഗ്. ഇത് പരീക്ഷിക്കപ്പെടുന്ന കോഡിനെ ഒറ്റപ്പെടുത്താനും ഡാറ്റാബേസുകൾ, എപിഐകൾ, അല്ലെങ്കിൽ ഫയൽ സിസ്റ്റങ്ങൾ പോലുള്ള ബാഹ്യ സിസ്റ്റങ്ങളെ ആശ്രയിക്കുന്നത് ഒഴിവാക്കാനും നിങ്ങളെ അനുവദിക്കുന്നു.
മോക്കിംഗിന്റെ പ്രയോജനങ്ങൾ
- കോഡിനെ ഒറ്റപ്പെടുത്തുന്നു: ബാഹ്യ ഡിപൻഡൻസികളെ ആശ്രയിക്കാതെ കോഡ് ഒറ്റയ്ക്ക് പരീക്ഷിക്കുക.
- പ്രവർത്തനം നിയന്ത്രിക്കുന്നു: റിട്ടേൺ മൂല്യങ്ങളും എക്സെപ്ഷനുകളും പോലുള്ള ഡിപൻഡൻസികളുടെ പ്രവർത്തനം നിർവചിക്കുക.
- ടെസ്റ്റുകളുടെ വേഗത കൂട്ടുന്നു: വേഗത കുറഞ്ഞതോ വിശ്വസനീയമല്ലാത്തതോ ആയ ബാഹ്യ സിസ്റ്റങ്ങൾ ഒഴിവാക്കുക.
- എഡ്ജ് കേസുകൾ പരീക്ഷിക്കുന്നു: യഥാർത്ഥ സാഹചര്യങ്ങളിൽ പുനർനിർമ്മിക്കാൻ പ്രയാസമുള്ള പിശകുകളും എഡ്ജ് കേസുകളും അനുകരിക്കുക.
unittest.mock ലൈബ്രറി ഉപയോഗിക്കുന്നത്
മോക്കുകൾ ഉണ്ടാക്കുന്നതിനായി പൈത്തൺ unittest.mock ലൈബ്രറി നൽകുന്നു. പൈടെസ്റ്റ് unittest.mock-മായി സുഗമമായി സംയോജിക്കുന്നു, ഇത് നിങ്ങളുടെ ടെസ്റ്റുകളിൽ ഡിപൻഡൻസികൾ മോക്ക് ചെയ്യുന്നത് എളുപ്പമാക്കുന്നു.
അടിസ്ഥാന മോക്കിംഗ് ഉദാഹരണം
ഒരു ബാഹ്യ എപിഐയിൽ നിന്ന് ഡാറ്റ വീണ്ടെടുക്കുന്ന ഒരു ഫംഗ്ഷൻ നിങ്ങൾക്കുണ്ടെന്ന് കരുതുക:
import requests
def get_data_from_api(url):
response = requests.get(url)
response.raise_for_status() # Raise an exception for bad status codes
return response.json()
എപിഐയിലേക്ക് യഥാർത്ഥത്തിൽ ഒരു അഭ്യർത്ഥന നടത്താതെ ഈ ഫംഗ്ഷൻ പരീക്ഷിക്കുന്നതിന്, നിങ്ങൾക്ക് requests.get ഫംഗ്ഷൻ മോക്ക് ചെയ്യാം:
import pytest
import requests
from unittest.mock import patch
@patch("requests.get")
def test_get_data_from_api(mock_get):
# Configure the mock to return a specific response
mock_get.return_value.json.return_value = {"data": "test data"}
mock_get.return_value.status_code = 200
# Call the function being tested
data = get_data_from_api("https://example.com/api")
# Assert that the mock was called with the correct URL
mock_get.assert_called_once_with("https://example.com/api")
# Assert that the function returned the expected data
assert data == {"data": "test data"}
ഈ ഉദാഹരണത്തിൽ, @patch("requests.get") ഡെക്കറേറ്റർ requests.get ഫംഗ്ഷനെ ഒരു മോക്ക് ഒബ്ജക്റ്റ് ഉപയോഗിച്ച് മാറ്റിസ്ഥാപിക്കുന്നു. mock_get ആർഗ്യുമെന്റ് ആണ് ആ മോക്ക് ഒബ്ജക്റ്റ്. തുടർന്ന് നമുക്ക് ഒരു നിർദ്ദിഷ്ട പ്രതികരണം നൽകുന്നതിനായി മോക്ക് ഒബ്ജക്റ്റിനെ കോൺഫിഗർ ചെയ്യാനും അത് ശരിയായ യുആർഎൽ ഉപയോഗിച്ചാണ് വിളിച്ചതെന്ന് ഉറപ്പുവരുത്താനും കഴിയും.
ഫിക്സ്ചറുകൾ ഉപയോഗിച്ചുള്ള മോക്കിംഗ്
മോക്കുകൾ ഉണ്ടാക്കാനും നിയന്ത്രിക്കാനും നിങ്ങൾക്ക് ഫിക്സ്ചറുകൾ ഉപയോഗിക്കാം. ഒന്നിലധികം ടെസ്റ്റുകളിൽ മോക്കുകൾ പങ്കിടുന്നതിനോ അല്ലെങ്കിൽ കൂടുതൽ സങ്കീർണ്ണമായ മോക്ക് സജ്ജീകരണങ്ങൾ ഉണ്ടാക്കുന്നതിനോ ഇത് ഉപയോഗപ്രദമാകും.
import pytest
import requests
from unittest.mock import Mock
@pytest.fixture
def mock_api_get():
mock = Mock()
mock.return_value.json.return_value = {"data": "test data"}
mock.return_value.status_code = 200
return mock
@pytest.fixture
def patched_get(mock_api_get, monkeypatch):
monkeypatch.setattr(requests, "get", mock_api_get)
return mock_api_get
def test_get_data_from_api(patched_get):
# Call the function being tested
data = get_data_from_api("https://example.com/api")
# Assert that the mock was called with the correct URL
patched_get.assert_called_once_with("https://example.com/api")
# Assert that the function returned the expected data
assert data == {"data": "test data"}
ഇവിടെ, mock_api_get ഒരു മോക്ക് ഉണ്ടാക്കി അത് റിട്ടേൺ ചെയ്യുന്നു. patched_get പിന്നീട് യഥാർത്ഥ `requests.get`-നെ മോക്ക് ഉപയോഗിച്ച് മാറ്റിസ്ഥാപിക്കാൻ പൈടെസ്റ്റിന്റെ ഒരു ഫിക്സ്ചറായ monkeypatch ഉപയോഗിക്കുന്നു. ഇത് മറ്റ് ടെസ്റ്റുകൾക്ക് അതേ മോക്ക് ചെയ്ത എപിഐ എൻഡ്പോയിന്റ് ഉപയോഗിക്കാൻ അനുവദിക്കുന്നു.
അഡ്വാൻസ്ഡ് മോക്കിംഗ് ടെക്നിക്കുകൾ
പൈടെസ്റ്റും unittest.mock-ഉം നിരവധി അഡ്വാൻസ്ഡ് മോക്കിംഗ് ടെക്നിക്കുകൾ വാഗ്ദാനം ചെയ്യുന്നു, അവയിൽ ഉൾപ്പെടുന്നവ:
- സൈഡ് എഫക്റ്റുകൾ (Side Effects): ഇൻപുട്ട് ആർഗ്യുമെന്റുകളെ അടിസ്ഥാനമാക്കി മോക്കുകൾക്ക് കസ്റ്റം സ്വഭാവം നിർവചിക്കുക.
- പ്രോപ്പർട്ടി മോക്കിംഗ് (Property Mocking): ഒബ്ജക്റ്റുകളുടെ പ്രോപ്പർട്ടികൾ മോക്ക് ചെയ്യുക.
- കോൺടെക്സ്റ്റ് മാനേജറുകൾ (Context Managers): താൽക്കാലികമായി മാറ്റിസ്ഥാപിക്കുന്നതിനായി കോൺടെക്സ്റ്റ് മാനേജറുകൾക്കുള്ളിൽ മോക്കുകൾ ഉപയോഗിക്കുക.
സൈഡ് എഫക്റ്റുകൾ
നിങ്ങളുടെ മോക്കുകൾക്ക് ലഭിക്കുന്ന ഇൻപുട്ട് ആർഗ്യുമെന്റുകളെ അടിസ്ഥാനമാക്കി അവയ്ക്ക് കസ്റ്റം സ്വഭാവം നിർവചിക്കാൻ സൈഡ് എഫക്റ്റുകൾ നിങ്ങളെ അനുവദിക്കുന്നു. വ്യത്യസ്ത സാഹചര്യങ്ങളോ പിശകുകളോ അനുകരിക്കുന്നതിന് ഇത് ഉപയോഗപ്രദമാണ്.
import pytest
from unittest.mock import Mock
def test_side_effect():
mock = Mock()
mock.side_effect = [1, 2, 3]
assert mock() == 1
assert mock() == 2
assert mock() == 3
with pytest.raises(StopIteration):
mock()
ഈ മോക്ക് തുടർച്ചയായ കോളുകളിൽ 1, 2, 3 എന്നിവ നൽകുന്നു, ലിസ്റ്റ് തീരുമ്പോൾ `StopIteration` എക്സെപ്ഷൻ നൽകുന്നു.
പ്രോപ്പർട്ടി മോക്കിംഗ്
ഒബ്ജക്റ്റുകളിലെ പ്രോപ്പർട്ടികളുടെ പ്രവർത്തനം മോക്ക് ചെയ്യാൻ പ്രോപ്പർട്ടി മോക്കിംഗ് നിങ്ങളെ അനുവദിക്കുന്നു. മെത്തേഡുകളേക്കാൾ ഒബ്ജക്റ്റ് പ്രോപ്പർട്ടികളെ ആശ്രയിക്കുന്ന കോഡ് പരീക്ഷിക്കുന്നതിന് ഇത് ഉപയോഗപ്രദമാണ്.
import pytest
from unittest.mock import patch
class MyClass:
@property
def my_property(self):
return "original value"
def test_property_mocking():
obj = MyClass()
with patch.object(obj, "my_property", new_callable=pytest.PropertyMock) as mock_property:
mock_property.return_value = "mocked value"
assert obj.my_property == "mocked value"
ഈ ഉദാഹരണം MyClass ഒബ്ജക്റ്റിന്റെ my_property എന്ന പ്രോപ്പർട്ടി മോക്ക് ചെയ്യുന്നു, ഇത് ടെസ്റ്റ് സമയത്ത് അതിന്റെ റിട്ടേൺ മൂല്യം നിയന്ത്രിക്കാൻ നിങ്ങളെ അനുവദിക്കുന്നു.
കോൺടെക്സ്റ്റ് മാനേജറുകൾ
കോൺടെക്സ്റ്റ് മാനേജറുകൾക്കുള്ളിൽ മോക്കുകൾ ഉപയോഗിക്കുന്നത് ഒരു നിർദ്ദിഷ്ട കോഡ് ബ്ലോക്കിനായി ഡിപൻഡൻസികളെ താൽക്കാലികമായി മാറ്റിസ്ഥാപിക്കാൻ നിങ്ങളെ അനുവദിക്കുന്നു. ബാഹ്യ സിസ്റ്റങ്ങളുമായോ റിസോഴ്സുകളുമായോ ഇടപഴകുന്ന കോഡ് പരീക്ഷിക്കുന്നതിന് ഇത് ഉപയോഗപ്രദമാണ്, കാരണം അവ ഒരു നിശ്ചിത സമയത്തേക്ക് മാത്രം മോക്ക് ചെയ്താൽ മതി.
import pytest
from unittest.mock import patch
def test_context_manager_mocking():
with patch("os.path.exists") as mock_exists:
mock_exists.return_value = True
assert os.path.exists("dummy_path") is True
# The mock is automatically reverted after the 'with' block
# Ensure the original function is restored, although we can't really assert
# the real `os.path.exists` function's behavior without a real path.
# The important thing is that the patch is gone after the context.
print("Mock has been removed")
പാരാമീറ്ററൈസേഷനും മോക്കിംഗും സംയോജിപ്പിക്കുന്നു
ഈ രണ്ട് ശക്തമായ ടെക്നിക്കുകളും സംയോജിപ്പിച്ച് കൂടുതൽ സങ്കീർണ്ണവും ഫലപ്രദവുമായ ടെസ്റ്റുകൾ ഉണ്ടാക്കാൻ കഴിയും. വ്യത്യസ്ത മോക്ക് കോൺഫിഗറേഷനുകൾ ഉപയോഗിച്ച് വ്യത്യസ്ത സാഹചര്യങ്ങൾ പരീക്ഷിക്കുന്നതിന് നിങ്ങൾക്ക് പാരാമീറ്ററൈസേഷൻ ഉപയോഗിക്കാം.
import pytest
import requests
from unittest.mock import patch
def get_user_data(user_id):
url = f"https://api.example.com/users/{user_id}"
response = requests.get(url)
response.raise_for_status()
return response.json()
@pytest.mark.parametrize(
"user_id, expected_data",
[
(1, {"id": 1, "name": "John Doe"}),
(2, {"id": 2, "name": "Jane Smith"}),
],
)
@patch("requests.get")
def test_get_user_data(mock_get, user_id, expected_data):
mock_get.return_value.json.return_value = expected_data
mock_get.return_value.status_code = 200
data = get_user_data(user_id)
assert data == expected_data
mock_get.assert_called_once_with(f"https://api.example.com/users/{user_id}")
ഈ ഉദാഹരണത്തിൽ, test_get_user_data ഫംഗ്ഷൻ വ്യത്യസ്ത user_id, expected_data മൂല്യങ്ങൾ ഉപയോഗിച്ച് പാരാമീറ്ററൈസ് ചെയ്തിരിക്കുന്നു. @patch ഡെക്കറേറ്റർ requests.get ഫംഗ്ഷൻ മോക്ക് ചെയ്യുന്നു. പൈടെസ്റ്റ് ഈ ടെസ്റ്റ് ഫംഗ്ഷൻ രണ്ടുതവണ പ്രവർത്തിപ്പിക്കും, ഓരോ പാരാമീറ്റർ സെറ്റിനും ഓരോ തവണ വീതം, അതത് expected_data നൽകുന്നതിനായി മോക്ക് കോൺഫിഗർ ചെയ്തിരിക്കും.
അഡ്വാൻസ്ഡ് ഫിക്സ്ചറുകൾ ഉപയോഗിക്കുന്നതിനുള്ള മികച്ച രീതികൾ
- ഫിക്സ്ചറുകൾക്ക് വ്യക്തമായ ലക്ഷ്യം നൽകുക: ഓരോ ഫിക്സ്ചറിനും വ്യക്തവും നിർദ്ദിഷ്ടവുമായ ഒരു ലക്ഷ്യം ഉണ്ടായിരിക്കണം.
- ഉചിതമായ സ്കോപ്പുകൾ ഉപയോഗിക്കുക: റിസോഴ്സ് ഉപയോഗം ഒപ്റ്റിമൈസ് ചെയ്യുന്നതിന് ഉചിതമായ ഫിക്സ്ചർ സ്കോപ്പ് (ഫംഗ്ഷൻ, മൊഡ്യൂൾ, സെഷൻ) തിരഞ്ഞെടുക്കുക.
- ഫിക്സ്ചറുകൾ ഡോക്യുമെന്റ് ചെയ്യുക: ഓരോ ഫിക്സ്ചറിന്റെയും ഉദ്ദേശ്യവും ഉപയോഗവും വ്യക്തമായി രേഖപ്പെടുത്തുക.
- അമിതമായ മോക്കിംഗ് ഒഴിവാക്കുക: പരീക്ഷിക്കുന്ന കോഡിനെ ഒറ്റപ്പെടുത്താൻ ആവശ്യമായ ഡിപൻഡൻസികൾ മാത്രം മോക്ക് ചെയ്യുക.
- വ്യക്തമായ അസേർഷനുകൾ എഴുതുക: നിങ്ങളുടെ അസേർഷനുകൾ വ്യക്തവും നിർദ്ദിഷ്ടവുമാണെന്ന് ഉറപ്പാക്കുക, പരീക്ഷിക്കുന്ന കോഡിന്റെ പ്രതീക്ഷിക്കുന്ന പ്രവർത്തനം പരിശോധിക്കുക.
- ടെസ്റ്റ്-ഡ്രിവൺ ഡെവലപ്മെന്റ് (TDD) പരിഗണിക്കുക: കോഡ് എഴുതുന്നതിന് മുമ്പ് നിങ്ങളുടെ ടെസ്റ്റുകൾ എഴുതുക, വികസന പ്രക്രിയയെ നയിക്കാൻ ഫിക്സ്ചറുകളും മോക്കുകളും ഉപയോഗിക്കുക.
ഉപസംഹാരം
പൈടെസ്റ്റിന്റെ അഡ്വാൻസ്ഡ് ഫിക്സ്ചർ ടെക്നിക്കുകളായ പാരാമീറ്ററൈസ്ഡ് ടെസ്റ്റിംഗും മോക്ക് ഇന്റഗ്രേഷനും, കരുത്തുറ്റതും കാര്യക്ഷമവും പരിപാലിക്കാൻ എളുപ്പമുള്ളതുമായ ടെസ്റ്റുകൾ എഴുതുന്നതിനുള്ള ശക്തമായ ടൂളുകൾ നൽകുന്നു. ഈ ടെക്നിക്കുകളിൽ വൈദഗ്ദ്ധ്യം നേടുന്നതിലൂടെ, നിങ്ങളുടെ പൈത്തൺ കോഡിന്റെ ഗുണനിലവാരം ഗണ്യമായി മെച്ചപ്പെടുത്താനും നിങ്ങളുടെ ടെസ്റ്റിംഗ് വർക്ക്ഫ്ലോ കാര്യക്ഷമമാക്കാനും കഴിയും. വ്യക്തവും കേന്ദ്രീകൃതവുമായ ഫിക്സ്ചറുകൾ ഉണ്ടാക്കുന്നതിലും, ഉചിതമായ സ്കോപ്പുകൾ ഉപയോഗിക്കുന്നതിലും, സമഗ്രമായ അസേർഷനുകൾ എഴുതുന്നതിലും ശ്രദ്ധ കേന്ദ്രീകരിക്കാൻ ഓർമ്മിക്കുക. പരിശീലനത്തിലൂടെ, ഒരു സമഗ്രവും ഫലപ്രദവുമായ ടെസ്റ്റിംഗ് സ്ട്രാറ്റജി ഉണ്ടാക്കാൻ പൈടെസ്റ്റിന്റെ ഫിക്സ്ചർ സിസ്റ്റത്തിന്റെ മുഴുവൻ കഴിവുകളും പ്രയോജനപ്പെടുത്താൻ നിങ്ങൾക്ക് സാധിക്കും.