Code maturity - minnie0531/fastapi-template GitHub Wiki
๊ฐ๋ฐ์์ ๊ฐ๋ฐ ํ๋ก์ ํธ๊ฐ ๋ง์ ์ง์ ๋ฐ๋ผ ํ์คํ๊ฐ ์ค์ํด ์ง๋๋ค. ๊ทธ ์ค์์ ์ฌ๊ธฐ์ ๋ค๋ค๋ณผ ๋ด์ฉ์ ์ฝ๋์ ๋ํ ๊ฒ์ผ๋ก ์ด๋ป๊ฒ ์ฝ๋์ ์ฑ์๋๋ฅผ ์ฌ๋ฆฌ๊ณ , ์ ์ง๋ณด์์ ๋๋ฒ๊น ์ด ์ฌ์์ง ์ ์๋์ง์ ๋ํด ์ด์ผ๊ธฐ ํ๋ ค ํฉ๋๋ค. ์ฝ๋์ ๋ํ ๋ถ์์ ์ ์ ๋ถ์๊ณผ ๋์ ๋ถ์์ผ๋ก ๋๋ ์ ์์ผ๋ฉฐ, ์ ์ ๋ถ์์ผ๋ก formatter์ linter๋ฅผ, ๋์ ๋ถ์์ผ๋ก code coverage์ ๋ํด ๋ค๋ฃจ๋๋ก ํ๊ฒ ์ต๋๋ค.
formatter and linter
์ฌ๋ฌ ์ฌ๋์ด ํ์ ํ์ฌ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ ๊ฒฝ์ฐ ์ฝ๋์คํ์ผ์ ๋ํ ์ ์๊ฐ ์๋ค๋ฉด ๊ฐ์ธ ๋ง๋ค ๋ค๋ฅธ ํ์์ผ๋ก ๊ฐ๋ฐ๋ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค. ๋๊ตฐ๊ฐ๋ if ๋ค์ {} ์ ์์น๋ฅผ ๋ฐ๋ก ์ฐ๋ ๊ฒ์ ์ ํธํ๊ณ ์ด๋ค ์ฌ๋์ ๋ค์ ๋ผ์ธ์ ์์นํ๋ ๊ฒ์ ์ ํธ ํฉ๋๋ค. ํจ์ ์ ์ ํ ๋ค์ ๋ค๋ฅธ ํจ์์ ์ ์๊ฐ ์ฌ ๋ blank line์ ์ผ๋งํผ ์ฌ์ฉํ ์ง ๋ฑ ๋ค์ํ ์ ํธ๊ฐ ์์ ๊ฒ์ด๊ณ ์ด๋ ๊ณ ์ค๋ํ ์ฝ๋์ ๋ฐ์๋๊ฒ ๋ ๊ฒ์ ๋๋ค. ๋ค์ํ ์ฝ๋ ์คํ์ผ์ ํ๋ก์ ํธ์ ๋ํ ์ ์ง๋ณด์๋ฅผ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค. ๋ค์ ๋งํ๋ฉด ์ฝ๋์ ๋ํ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง๊ณ ๊ทธ ๊ฒฐ๊ณผ ์๋ฌ๋ฅผ ๋ฐ๊ฒฌํ๋ ๊ฒ์ด ์ฝ์ง ์์ ๋๋ฒ๊น ์ด ์ด๋ ค์ ์ง ๊ฒ์ ๋๋ค. ๋ชจ๋๊ฐ ๋์ผํ ์ฝ๋ ์คํ์ผ์ ์ฌ์ฉํ๊ฒ ๋๋ค๋ฉด ์์ ๋จ์ ์ด ๋ณด์ ๋ ๊ฒ์ ๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ formatter์ linter๋ฅผ ์ด์ฉํ์ฌ code format์ ๋ํ violation์ ์ฒดํฌํ๊ณ ๋ฐ๋ก ์ก์ ์ ์์ต๋๋ค.
- PEP8
pep8์ python ๊ณต์ ์คํ์ผ ๊ฐ์ด๋ ์ ๋๋ค. ์๋์ ๊ฐ์ด ์ฝ๋ ์คํ์ผ์ ๋ํด ์ ์๊ฐ ๋์ด ์์ต๋๋ค.
Spaces are the preferred indentation method.
Use 4 spaces per indentation level.
Limit all lines to a maximum of 79 characters.
Separate top-level function and class definitions with two blank lines.
Method definitions inside a class are surrounded by a single blank line.
Imports should be grouped in the following order:
- Standard library imports.
- Related third party imports.
- Local application/library specific imports.
- A blank line between each group of imports.
Formatter์ linter ์ ์ข ๋ฅ
linter์ formatter์ ์ข ๋ฅ๋ ๋งค์ฐ ๋ค์ํด์ ๊ฐ๋ฐ๊ทธ๋ฃน์์ ์ ํ์ ์ผ๋ก ์ ์ฉ ๊ฐ๋ฅ ํฉ๋๋ค.
-
pycodestyle
Pycodestyle์ ๊ณต์ linter๋ก PEP8์ ์คํ์ผ ์ปจ๋ฒค์ ์ ๊ธฐ๋ฐ์ผ๋ก python ์ฝ๋๋ฅผ ์ฒดํฌํฉ๋๋ค.
-
pylint
pylint๋ python linter์ค ํ๋๋ก ์์ค์ฝ๋ ์ฒดํฌ ๋ฐ ๋ฒ๊ทธ, qulaity ์ฒดํฌ๋ฅผ ํฉ๋๋ค. ๋จ์ํ PEP8์ ์ฌ์ฉํ๋ ๊ฒ ๋ณด๋ค ๋ง์ verificiation checks์ ์ต์ ์ ๊ฐ๊ณ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๊ฐ ๋ผ์ธ์ ๊ธธ์ด๋ฅผ ์ฒดํฌ ํ๋ค๊ฑฐ๋ ๋ณ์ ๋ช ์ด ํ๋ก์ ํธ์ ๊ธฐ์ค์ ๋ง๊ฒ ์ ์ฉ ๋์ด ์๋์ง ์ ์ธ๋ ์ธํฐํ์ด์ค๊ฐ ์ ๋ง๋ก ๊ตฌํ ๋์ด ์๋ ์ง ๋ฑ PEP8์ ์๋ ์ถ๊ฐ์ ์ธ ๋ด์ฉ๋ ๊ฐ๊ณ ์์ต๋๋ค. ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ linter๋ก VSCode์ ๊ธฐ๋ณธ linter์ ๋๋ค.
-
pyflakes
pyflakes๋ ์์ ๋ค๋ฅธ linter ๋ค๋ฅด๊ฒ ์คํ์ผ์ ๋ํ ์ฒดํฌ๊ฐ ์๋๋ผ ํ๋ก์ ํธ์ ๊ฐ ํ์ผ์์ ๋ฐ์๋ ์ ์๋ logistic erorrs , syntax eorror ๋ฑ์ ํ์ธํฉ๋๋ค.
-
flake8
flake8์ pyflakes, pycodlestyle ๊ณผ Mccabe script ๋ฅผ ๊ฐ์ธ๊ณ ์๋ wrapper ์ ๋๋ค. McCabe script์ ๋ ์ฝ๋์ ๋ณต์ก์ฑ์ ์ค์ด๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
-
black
black์ python code auto-formatter๋ก ์ ์ฒด ํ์ผ์ ๋ํด reformattingํด์ฃผ๊ณ string์ ๊ฒฝ์ฐ " ์๊ฐ๊ณ ๋๋ก ๋ง๋ญ๋๋ค. black์ python ๊ณต์ community์์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ฉฐ line-length๋ฅผ ์ ์ธํ๊ณ format์ ๋ํ ์ถ๊ฐ์ ์ธ configuration์ ํ ์ ์์ต๋๋ค.
-
autopep8
autopep8์ ์๋์ผ๋ก python code๋ฅผ style๋ก reformatting ํด ์ค๋๋ค. autopep8์ pycodesstyle ์์ ๋ฆฌํฌํธ ๋๋ ๋๋ถ๋ถ์ ์ด์๋ฅผ ๋ฐ๋ก ๊ณ ์นฉ๋๋ค.
-
yapf
yapf์ python formatter์ค ํ๋๋ก google์์ ์ฌ์ฉํ๊ณ ์ ์ง๋ณด์ ํฉ๋๋ค. configuration์ด ์์ ๋ก์ด ๊ฒ์ด ํน์ง์ ๋๋ค.
์ฌ๊ธฐ์์๋ ๋ค์ํ๊ฒ linter๋ฅผ ์ ์ฉํ ์ ์๋ flake8๊ณผ ์ฐ๋ฆฌ์ configuration์ด ์ถ๊ฐ์ ์ผ๋ก ๋ค์ด๊ฐ์ง ์์๋ ๋๋ black์ ์ฌ์ฉํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
IDE์์ lint ์ ์ฉํ๊ธฐ
vscode https://code.visualstudio.com/docs/python/linting
- command palette ์์ย
python: select lint๋ฅผ ์ ๋ ฅํ์ฌ flake8 ์ ํ - command palette ์์ย
python: run linting์ ํตํ์ฌ lint ํ์ฑํ
pre-commit์ ์ด์ฉํ commit check & ci improvement.
pre-commit์ installํ๊ฒ ๋๋ฉด ./git/hook/pre-commitํด๋๊ฐ ์์ฑ๋๊ณ ์ด๋ฅผ ๋ฐํ์ผ๋ก git commit์ .pre-commit-config.yaml ์ ์ ์๋ ๋ชจ๋์ ์คํํ๊ฒ ๋ฉ๋๋ค.
flake8 pre-commit : https://flake8.pycqa.org/en/latest/user/using-hooks.html
repos:
- repo: https://github.com/ambv/black
rev: 21.7b0
hooks:
- id: black
language_version: python3.9
- repo: https://github.com/pycqa/flake8
rev: 3.9.2
hooks:
- id: flake8
Configuration for flake8
[flake8]
ignore = E203, E266, E501, W503, F403, F401 # set ignore errors
max-line-length = 89
max-complexity = 18
select = B,C,E,F,W,T4,B9
# select
# C90 : Allย C90ย class violations are reported when the user specifies
# E : llย Eย class violations are โerrorsโ reported by pycodestyle
# F : Allย Fย class violations are reported by pyflakes
# W : Allย Wย class violations are โwarningsโ reported by pycodestyle
pre-commit์ ์ํํ๋ฉด ์๋์ ๊ฐ์ด ๋๊ณ , git commit ์ปค๋งจ๋๋ฅผ ์ฌ์ฉํด๋ ๋์ผํ ์ ์ฐจ๋ฅผ ๊ฑฐ์นฉ๋๋ค.
pre-commit run --all-files
black....................................................................Passed
flake8...................................................................Passed
Error and violation code
์๋ ๋งํฌ๋ PEP8์ ์ ์๋ ERROR ์ Violation code์ ๋ํ ์ค๋ช ์ ๋๋ค. ์ ignoreํญ๋ชฉ์์ ํ์์ ๋ฐ๋ผ ๋ฃ์ด์ฃผ๋ฉด, ํด๋น ํญ๋ชฉ์ ์ฒดํฌํ์ง ์์ต๋๋ค.
https://flake8.pycqa.org/en/latest/user/error-codes.html
https://pep8.readthedocs.io/en/latest/intro.html
Code coverage
์ฝ๋์ Quality๋ฅผ ๋์ด๋ ๋ฐฉ๋ฒ์ค ํ๋๋ ํ ์คํธ์ ์์ฑ์ ๋๋ค. Code coverage๋ ์ผ๋ง๋ ํ ์คํธ๊ฐ ์๋์ด ์๋์ง๋ฅผ ์์ ๋ณด๋ ์งํ๋ก, coverage๊ฐ ๋์ ์๋ก ํ๋ก๊ทธ๋จ์ด ๋์ํ ๋ ์ค๋ฅ๋ฅผ ์ค์ผ ์ ์์ต๋๋ค. ์์คํ ์ด ๋ณต์กํ ์๋ก, ๋ง์ ๊ฐ๋ฐ์๊ฐ ๊ฐ๋ฐ์ ์ฐธ์ฌํ ์๋ก ํ ์คํธ์ ํ ์คํธ coverage check๋ ๊ฐ๋ฐ์ ๋ฐ๋์ ํ์ํ ์์ ์ ๋๋ค.
์ค์น
pip install coverage
run
coverage run --omit "venv/*" test_file_path
report
coverage report
coverage reportName Stmts Miss Cover
--------------------------------------------
app/main.py 8 1 88%
app/routers/query.py 5 1 80%
test/test_endpoints.py 15 6 60%
--------------------------------------------
TOTAL 28 8 71%
HTML report
coverage html
coverage result in index.html
main.html coverage