LearningPython TutorialVirtual Environments, pip & Testing
CHAPTER 22 · DEPENDENCIES & SOFTWARE QUALITY

Python Virtual Environments, pip & Testing

Real Python projects sirf code se nahi chalte — unhe isolated dependencies, reproducible setup, automated tests aur practical debugging workflow bhi chahiye. Is chapter me venv, pip, dependency files, unittest, mocking, logging aur test-first thinking ko beginner-friendly way me samjhenge.

English + Hinglish86 min readLocal terminal + online practice
Playground note: python -m venv aur pip shell/terminal commands hain. BrounStack Python Playground Python code run karta hai, full operating-system terminal nahi. In commands ko local Terminal, PowerShell, CMD, VS Code terminal ya suitable cloud shell me run karo.

Why virtual environments matter

Different projects ko same package ke different versions chahiye ho sakte hain. Virtual environment ek project-specific Python environment create karta hai jisme installed packages global/system Python se largely isolate rehte hain.

Hinglish Explanation

Project A ko package version 1 chahiye aur Project B ko version 2. Dono ko global Python me install karoge to conflict ho sakta hai. venv har project ke liye alag dependency space deta hai.

Create a virtual environment

terminalShell
python -m venv .venv

.venv conventional folder name hai, mandatory nahi. python -m venv currently selected Python interpreter ka venv module use karta hai.

Windows nuance: Kuch systems par command py -m venv .venv ho sakti hai. macOS/Linux par python3 -m venv .venv common hai.

Activate the environment

Windows PowerShellShell
.\.venv\Scripts\Activate.ps1
Windows CMDShell
.venv\Scripts\activate.bat
macOS / LinuxShell
source .venv/bin/activate

Activation mainly shell ke PATH ko adjust karta hai so python and related commands environment ke executables use karein. Activation convenience hai; environment interpreter ko direct path se bhi run kiya ja sakta hai.

Verify which Python is active

terminalShell
python -c "import sys; print(sys.executable)"
python --version

Interpreter path check karna environment confusion debug karne ka reliable first step hai.

Deactivate

terminalShell
deactivate

Deactivate current shell ko normal environment state par return karta hai; project files delete nahi hote.

pip kya hai?

pip Python packages install/manage karne ka standard package installer hai. Beginner projects me interpreter mismatch avoid karne ke liye python -m pip form useful hai because it clearly selected Python interpreter se pip run karta hai.

pip-basicsShell
python -m pip --version
python -m pip install package-name
python -m pip uninstall package-name
python -m pip show package-name
python -m pip list

Third-party package install karne se pehle package name, official documentation, maintenance status aur trustworthiness verify karo.

Package version specifiers

terminalShell
python -m pip install "example-package==1.4.2"
python -m pip install "example-package>=1.4,<2"

== exact version pin karta hai. Range specifiers compatibility window allow karte hain. Kaunsi strategy best hai wo application/library workflow par depend karti hai.

requirements.txt basics

Simple applications me dependency list text file me store karna common hai.

requirements.txtText
requests==2.32.5
rich==14.1.0
terminalShell
python -m pip install -r requirements.txt

Example versions illustrative hain. Real project me package compatibility and security updates verify karo.

pip freeze — useful but understand what it does

terminalShell
python -m pip freeze > requirements.txt

pip freeze environment me installed packages ka snapshot deta hai, including transitive dependencies. Ye quick reproducibility ke liye useful hai, but intentional top-level dependencies aur lockfile strategy ka complete replacement har project me nahi.

pyproject.toml overview

Modern Python projects frequently project metadata, build configuration and direct dependencies ke liye pyproject.toml use karte hain. Exact format selected build/package tooling par depend karta hai.

pyproject.tomlTOML
[project]
name = "brounstack-demo"
version = "0.1.0"
dependencies = [
  "requests>=2.32,<3",
]

Beginner ke liye pehle venv + pip + simple requirements samajhna enough hai; packaging ecosystem ko gradually learn karo.

Do not commit the virtual environment folder

.venv/ generated environment hai. Normally Git repository me environment folder commit nahi karte; dependency declaration files commit karte hain.

.gitignoreText
.venv/
__pycache__/
*.pyc

Recreate a clean environment

Project portability test karne ka strong habit: fresh environment banao, declared dependencies install karo, then tests run karo. Agar project sirf old local environment me chal raha hai, hidden dependency ho sakti hai.

Common dependency problems

  • Wrong Python interpreter ke pip se package install karna.
  • Virtual environment activate kiya but editor another interpreter use kar raha hai.
  • Package installed hai but import name different hai.
  • Package version incompatible with your Python version.
  • Two dependencies incompatible versions demand kar rahi hain.
  • Global packages accidentally project issue hide kar dete hain.

Why automated tests?

Automated test known input/behavior ko repeatedly verify karta hai. Tests regression catch karte hain, refactoring confidence improve karte hain aur expected behavior document karne me help karte hain.

calculator.pyPython
def add(a, b):
    return a + b
simple-check.pyPython
def add(a, b):
    return a + b

assert add(2, 3) == 5
assert add(-1, 1) == 0
print("Checks passed")
Important: assert developer checks ke liye useful hai, but production input validation/security logic ke replacement ke roop me use mat karo. Python optimization modes assertions remove kar sakte hain.

Try simple assertions →

unittest basics

unittest Python standard library ka test framework hai.

test_math_tools.pyPython
import unittest


def percentage(score, total):
    if total <= 0:
        raise ValueError("total must be positive")
    return score / total * 100


class PercentageTests(unittest.TestCase):
    def test_normal_percentage(self):
        self.assertEqual(percentage(40, 50), 80)

    def test_zero_total_rejected(self):
        with self.assertRaises(ValueError):
            percentage(10, 0)


if __name__ == "__main__":
    unittest.main()

TestCase assertion helpers deta hai such as assertEqual, assertTrue, assertIn, assertIsNone and assertRaises.

Try unittest example →

Test naming and structure

Tests ko behavior-oriented names do: test_empty_cart_total_is_zero is more informative than test1. Arrange test data, call behavior, then assert result — simple Arrange/Act/Assert thinking readability improve karta hai.

setUp() for repeated test preparation

setup-example.pyPython
import unittest


class CartTests(unittest.TestCase):
    def setUp(self):
        self.items = [100, 250]

    def test_total(self):
        self.assertEqual(sum(self.items), 350)

    def test_item_count(self):
        self.assertEqual(len(self.items), 2)

setUp() each test method se pehle fresh state prepare kar sakta hai. Tests ko each other par depend nahi karna chahiye.

Test multiple cases with subTest()

subtests.pyPython
import unittest


def is_even(value):
    return value % 2 == 0


class EvenTests(unittest.TestCase):
    def test_cases(self):
        cases = [(2, True), (3, False), (10, True)]
        for value, expected in cases:
            with self.subTest(value=value):
                self.assertEqual(is_even(value), expected)

Run tests from the terminal

terminalShell
python -m unittest
python -m unittest discover
python -m unittest -v

Test discovery conventionally files/modules and test_* methods/classes ko identify karta hai according to unittest rules and project layout.

Test exceptions deliberately

Invalid-input behavior bhi contract ka part hai. Sirf happy path test mat karo.

errors.pyPython
import unittest


def age_group(age):
    if age < 0:
        raise ValueError("age cannot be negative")
    return "adult" if age >= 18 else "minor"


class AgeTests(unittest.TestCase):
    def test_negative_age(self):
        with self.assertRaisesRegex(ValueError, "negative"):
            age_group(-1)

Mock external dependencies

Tests ideally deterministic aur fast hone chahiye. Network, current time, email sending or external APIs ko real call karna unnecessary/flaky ho sakta hai. Standard library unittest.mock controlled replacement objects provide karta hai.

mock-example.pyPython
from unittest.mock import Mock

sender = Mock(return_value={"status": "sent"})
result = sender("student@example.com")

assert result["status"] == "sent"
sender.assert_called_once_with("student@example.com")

Mock behavior ko overuse mat karo. Useful boundary interactions mock karo; core business logic ko real objects/data ke saath test karna often clearer hai.

Test files safely with tempfile

tempfile-test.pyPython
from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as folder:
    path = Path(folder) / "notes.txt"
    path.write_text("Python", encoding="utf-8")
    assert path.read_text(encoding="utf-8") == "Python"

print("Temporary file test passed")

Temporary resources tests ko real user/project files accidentally overwrite karne se bachate hain.

pytest preview

pytest popular third-party testing framework hai with concise assertions, fixtures and plugins. Ye standard library ka part nahi, so environment me separately install karna hota hai.

terminalShell
python -m pip install pytest
python -m pytest

Course foundation ke liye unittest understanding enough hai; pytest baad me workflow simplify kar sakta hai.

Debugging workflow

  • Error message and traceback bottom se start karke relevant frames read karo.
  • Problem ko smallest reproducible input tak reduce karo.
  • Values/types inspect karo instead of guessing.
  • One change at a time karo and rerun focused test.
  • Fix ke baad regression test add karo.

Use breakpoint()

debug.pyPython
def average(scores):
    breakpoint()
    return sum(scores) / len(scores)

print(average([70, 80, 90]))

Local interactive terminal me breakpoint() debugger open kar sakta hai. Production code me accidental breakpoints leave mat karo.

Logging basics

logging.pyPython
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

student_count = 42
logger.info("Loaded %s students", student_count)

Production-style programs me structured logging repeated print() debugging se better control deta hai. Passwords, tokens and sensitive personal data logs me mat likho.

What should you test?

  • Core calculations and business rules.
  • Boundary values: empty input, zero, max/min, missing fields.
  • Expected exceptions and validation.
  • Data parsing/serialization.
  • Important integration boundaries with controlled dependencies.
  • Past bugs — each meaningful bug fix ke saath regression test valuable hai.

Common beginner mistakes

  • One global Python environment me every project ka package install karna.
  • pip command another interpreter se linked hone par confusion ignore karna.
  • .venv folder Git me commit kar dena.
  • Dependency versions/documentation track na karna.
  • pip freeze output ko blindly permanent dependency design samajhna.
  • Tests me only happy path cover karna.
  • Tests ko execution order par depend karna.
  • Real external API ko every unit test me call karna.
  • assert ko production validation/security mechanism banana.
  • Bug fix karna but regression test add na karna.
  • Debug logging me secrets print karna.

Beginner best practices

  • Har substantial project ke liye dedicated virtual environment use karo.
  • python -m pip use karke interpreter/package manager relation clear rakho.
  • Dependencies declare karo; generated environment folder commit mat karo.
  • Fresh environment me project setup periodically verify karo.
  • Small deterministic unit tests se start karo.
  • Tests independent and readable rakho.
  • External boundaries ko mock/fake when appropriate.
  • Traceback → minimal reproduction → focused test → fix → regression test workflow follow karo.

Chapter checklist

  • python -m venv .venv ka purpose clear hai?
  • Windows/macOS/Linux activation concept samajh aaya?
  • python -m pip se install/list/show/uninstall kar sakte ho?
  • requirements.txt and pip freeze ka difference/context samajh aaya?
  • unittest.TestCase based test likh sakte ho?
  • Expected exceptions test kar sakte ho?
  • setUp() and subTest() ka basic use clear hai?
  • Mocking and temporary files kab useful hain?
  • Traceback, breakpoint() and logging ka role clear hai?

Practice Task — Tested Student Result Package

Local machine par isolated environment + tests ke saath mini project banao.

  1. New folder create karo and .venv virtual environment banao.
  2. Environment activate karke interpreter path verify karo.
  3. student_results.py module banao.
  4. percentage(score, total) function add karo with validation.
  5. grade(percent) function add karo.
  6. summary(name, scores) function add karo.
  7. test_student_results.py me unittest tests likho.
  8. Normal percentage, boundary grades and invalid total test karo.
  9. At least one subTest() table-driven test banao.
  10. One expected ValueError test karo.
  11. Optional third-party package install karke pip list inspect karo, then uninstall karo.
  12. Dependencies ko suitable file me document karo.
  13. .venv/ ko .gitignore me add karo.
  14. Fresh environment recreate karke tests run karo.
  15. Intentional bug introduce karo, failing test observe karo, then fix it.

Open practice starter →