The short version
The list
- 1
Use pytest over unittest (modern Pune default)
pytest is the standard Python test runner — simpler assertion syntax (`assert x == y` not `self.assertEqual(x, y)`), powerful fixtures, parametrize, plugins ecosystem. unittest still works but pytest's developer-experience advantages dominate modern Pune Python codebases.
Why it matters: Asked at ~75% of Pune Python rounds. unittest knowledge useful for legacy maintenance; pytest is the modern hiring default.
Best for: Foundation; expected default at every modern Pune Python team.
- 2
Fixtures for shared setup + teardown
Define reusable setup via `@pytest.fixture` decorator; functions request them by name as arguments. Scope controls lifecycle: function (default), class, module, session. Use yield for cleanup: `yield value; cleanup()`. Replaces setUp/tearDown boilerplate.
Why it matters: Asked at ~65% of Pune rounds. Common gotcha: fixture scope mismatch (function-scoped fixture inside session-scoped — error).
Best for: Shared test infrastructure; database connections; HTTP clients.
- 3
Parametrize for testing multiple inputs
`@pytest.mark.parametrize('input, expected', [(1, 1), (2, 4), (3, 9)])` runs the test function once per parameter set with the values injected. Cleaner than loops; each parametrized case appears as separate test result. Add IDs for clarity: `parametrize(..., ids=['one', 'two', 'three'])`.
Why it matters: Asked at ~55% of Pune rounds. Data-driven testing pattern; differentiates from candidates writing duplicate test functions.
Best for: Boundary value testing; multiple input variations.
- 4
Mock external dependencies via unittest.mock or pytest-mock
`@patch('module.requests.get')` replaces requests.get with a Mock object for the test's duration. Use return_value for simple cases, side_effect for sequences or exceptions. pytest-mock provides cleaner `mocker` fixture: `mocker.patch('module.requests.get')`.
Why it matters: Asked at ~70% of Pune rounds. Mocking discipline differentiates production-ready candidates from prototype-only ones.
Best for: Isolating units; avoiding network/database calls in unit tests.
- 5
Use pytest-asyncio for async function testing
Async test: `@pytest.mark.asyncio\nasync def test_thing(): result = await fetch_data(); assert result == ...`. Configure via pytest.ini or pyproject.toml. Critical for testing FastAPI handlers + async LangChain agents + httpx clients — increasingly common in Pune Python product work.
Why it matters: Asked at ~40% of Pune product company rounds. Modern async-Python signal; rare at services-major fresher tier.
Best for: FastAPI + LangChain + httpx + any async codebase.
- 6
Test web apps via TestClient (FastAPI) or test_client (Flask)
FastAPI: `from fastapi.testclient import TestClient; client = TestClient(app); response = client.get('/endpoint'); assert response.status_code == 200`. Flask: `app.test_client()`. No real server needed — tests run in-process. Faster + more reliable than spinning up the server for tests.
Why it matters: Asked at ~50% of Pune Python web rounds. Walking through testing a complete endpoint flow signals real production experience.
Best for: API testing; integration tests for web frameworks.
- 7
Mock LLM API calls in agentic AI / RAG tests
Don't call real OpenAI / Anthropic APIs in tests (slow + costly + non-deterministic). Mock: `mocker.patch('openai.ChatCompletion.create', return_value=mock_response)`. For LangChain: use FakeChatModel or VCR-cassette pattern for deterministic LLM responses. Critical for AI engineer test discipline.
Why it matters: Asked at ~45% of Pune AI engineer rounds. Production-grade AI test discipline; differentiates beyond tutorial-quality candidates.
Best for: AI engineer testing; cost-controlled CI runs.
- 8
Property-based testing with Hypothesis
Generate hundreds of random inputs to find edge cases your hand-written examples miss: `@given(st.integers())\ndef test_sort_idempotent(xs): assert sorted(sorted(xs)) == sorted(xs)`. Hypothesis finds + shrinks failing examples automatically. Catches off-by-one + integer-overflow + empty-list bugs example-based tests miss.
Why it matters: Asked at ~25% of Pune product company rounds. Senior-fresher engineering rigour signal; rare at services-major fresher tier.
Best for: Algorithmic code; data-pipeline transformations; library code.
- 9
Coverage tracking with pytest-cov
`pytest --cov=mymodule --cov-report=term-missing` shows which lines + branches aren't covered. Aim for ~80% baseline (not 100% — diminishing returns on edge cases + setup code). Use `# pragma: no cover` for legitimately unreachable code (defensive raises).
Why it matters: Asked at ~50% of Pune product company rounds. Specifying a target coverage % shows engineering discipline; '100% coverage' answer signals inexperience.
Best for: Quality gates; CI coverage thresholds; identifying untested paths.
- 10
Test pyramid: unit > integration > E2E
Many unit tests (fast, isolated, easy to debug) → fewer integration tests (real database, real HTTP layer) → very few E2E tests (real browser, full stack). E2E catches user-visible bugs but is slow + flaky. Don't invert: heavy E2E + few unit tests is a maintenance nightmare.
Why it matters: Asked at ~55% of Pune rounds. Test-strategy thinking signal; senior-fresher differentiator from candidates who just write 'tests'.
Best for: Test-strategy maturity; production-engineering signal.
How we built this list
Strategies ranked by Pune Python interview-frequency from Archer Infotech's placement-cell debriefs over 2024-2026 cycles + production-use prevalence at Pune Python product companies (Druva, BrowserStack, GUVI, ZS Associates, Persistent Avaamo, Helpshift). pytest-first modern patterns prioritised; older unittest specifics kept where legacy maintenance matters. Async + AI testing patterns reflect rapidly-growing modern Pune product company hiring.
FAQs
Common questions about python testing strategies.
Should I learn unittest or pytest as a Pune Python fresher?
pytest first to working depth. unittest awareness for legacy codebase maintenance (Pune services-major projects often have years of unittest-based test suites). Modern Pune Python product companies + AI startups are pytest-first; spending fresher prep time on pytest patterns vs unittest specifics is the right allocation.
What test coverage % should I target for Pune fresher portfolio projects?
~70-80% is realistic + sufficient. Don't chase 100% — diminishing returns on edge cases + defensive code. Show that you understand what's covered + why some code intentionally isn't (e.g. `# pragma: no cover` for unreachable code). Recruiters value coverage discipline + intentional gaps over 100% theatre.
How do I mock LLM API calls without breaking tests when prompts change?
Three patterns: (1) Mock at the highest reasonable level — typically the orchestration function, not the LLM call directly. (2) Use VCR cassettes (vcr-langchain or vcrpy) to record real responses once + replay. (3) For chain testing, use LangChain's FakeChatModel or BatchModel that returns scripted responses by prompt content. The 'prompts change' problem is real — design tests around behaviour, not exact LLM output strings.
What's the most-failed Python testing question at Pune fresher interviews?
Mocking depth + scope. Candidates know `@patch` exists but miss: (1) where to patch (module that uses the import, not the module that defines it — patch at use-site), (2) Mock vs MagicMock (MagicMock auto-implements magic methods like __iter__), (3) side_effect for sequences + exceptions, (4) reset_mock + assert_called_with assertion patterns. Walking through 'mock a function called from another module' demonstrates real mocking maturity.