Testing, Security, and Deployment
Ensure quality, secure your app, containerize, automate, and deploy to cloud platforms with confidence.
Content
Linting and static analysis
Versions:
Watch & Learn
AI-discovered learning video
Sign in to watch the learning video for this topic.
Linting and Static Analysis — Make Your Code Behave Before Tests Do
Imagine your code base as a party. Linting is the friend who whispers "maybe wear shoes" before security shows up to check IDs and tests call the bouncers.
This lesson builds on what you already learned about integration tests with Flask and end to end testing. You know how tests catch functional bugs and E2E tests exercise the whole stack. Linting and static analysis are different: they find issues without running your code, often faster and earlier in the dev loop. They are essential for React frontends and Flask backends alike.
What linting and static analysis actually are
- Linting: lightweight, rule-based checks that enforce style, catch obvious mistakes, and sometimes auto-fix them. Think ESLint for JavaScript/React and flake8 or pylint for Python.
- Static analysis: deeper, often semantic checks. Type checkers and security analyzers fall here. Examples: mypy for Python types, TypeScript for JS/TS types, bandit for Python security checks, and more advanced analyzers that find potential runtime errors.
Why they matter
- Catch typos, unused vars, and inconsistent styles before a failing test or runtime crash.
- Enforce team conventions so code reviews focus on design, not style nitpicks.
- Detect security patterns and probable bugs that tests may miss.
How linting complements tests and integration checks
- Tests verify behavior; linting verifies intent and hygiene.
- Integration tests with Flask ensure endpoints work. Linting ensures your Flask view functions follow conventions, avoid common pitfalls, and that imports and async/await usage are sane.
- For React UIs, ESLint with React plugins flags bad JSX patterns, missing hook deps, or unused props before they cause strange UI bugs that tests may only catch later.
Think of this progression:
- Linting/static analysis prevents low-hanging bugs during dev.
- Unit and integration tests check correctness of logic.
- E2E tests verify full system behavior and UX.
Quick examples you can steal
ESLint for React (simple .eslintrc.js)
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended'
],
settings: {
react: {
version: 'detect'
}
},
rules: {
'react/prop-types': 'off', // if using TypeScript or prefer not to
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }]
}
}
Micro explanation: The react-hooks plugin will flag missing effect dependencies — a common source of subtle bugs you might otherwise only see in a live React app or E2E tests.
Python linting and type checking
- Use flake8 or pylint for style and simple errors.
- Use mypy for type checking.
Example pyproject.toml snippet for flake8 and mypy
[tool.flake8]
max-line-length = 88
extend-ignore = ['E203']
[tool.mypy]
python_version = 3.10
ignore_missing_imports = true
strict = false
Micro explanation: mypy will flag mismatches in function signatures or incorrect return types that unit tests might not directly cover.
Security static analysis
- For Python: bandit scans code for common security issues like unsafe eval usage, weak crypto, shell injection patterns.
- For JS: eslint-plugin-security and dependency vulnerability scanners (npm audit, yarn audit, or Snyk) help.
- Secret scanning: tools like detect-secrets or git-secrets prevent accidental commits of API keys.
Why run these in CI
- They catch vulnerabilities and secrets before deploy.
- Integrate them as blocking steps in your pipeline so a merge is prevented until action is taken.
Automate it: pre-commit hooks and CI
Local pre-commit hooks give instant feedback. CI enforces checks for all contributors.
Example .pre-commit-config.yaml
repos:
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.30.0
hooks:
- id: eslint
files: '\.(js|jsx|ts|tsx)$'
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.4.1
hooks:
- id: mypy
CI example: GitHub Actions step for linting
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install frontend deps
run: npm ci --prefix frontend
- name: Run ESLint
run: npm run lint --prefix frontend
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: 3.10
- name: Install backend deps
run: pip install -r requirements.txt
- name: Run flake8
run: flake8 backend
- name: Run mypy
run: mypy backend
Practical tips and tradeoffs
- Start with recommended presets and only tune rules that frequently block real work.
- Use auto-fix where safe (eslint --fix, black for Python) so style enforcement is mostly painless.
- Beware of noisy rules. If a rule triggers too often on legit patterns, either adjust its severity or scope it to a folder.
- Type checking gives significant value but has upfront cost. Adopt gradually with allow-listing and ignore_missing_imports when needed.
Common misunderstandings
- Linting will not replace tests. It will reduce trivial failures and catch many anti-patterns, but logic bugs still need tests.
- Static analysis is not perfect. False positives happen, and rules evolve. Treat them as guides, not infallible judges.
Quick checklist to add linting and static analysis to your CS50 web project
- Add ESLint with React plugin to the frontend and enable react-hooks rules.
- Add flake8 and mypy to the Flask backend; use black + isort for consistent formatting.
- Add bandit or similar security scanner for Python.
- Add pre-commit to run formatters and linters locally.
- Add a linting job to CI and fail the pipeline on errors.
- Run dependency audits regularly and enable secret scanning for repos.
Key takeaways
- Linting catches style and common errors early. It makes code reviews smoother and reduces flaky bugs.
- Static analysis (type checkers, security scanners) finds deeper issues before runtime. It pairs perfectly with your integration and E2E tests.
- Automate checks locally and in CI. Make the feedback immediate and the pipeline enforceable.
"When linting and static analysis run reliably, tests become meaningful and deploys become calmer."
Go add linting to your React components and Flask routes now. Your future self will send a thank-you commit.
Comments (0)
Please sign in to leave a comment.
No comments yet. Be the first to comment!