â±ïž ãã®èšäºã3è¡ã§ãŸãšãããš
â 3ä»¶ãããªãã£ãpytestãèŠçŽããXSSã»Jinjaã»AIããã³ããã»Geminiæ¥ç¶ã»CIãŸã§å®ã9ä»¶ãžåŒ·åããŸããã
â¡ ç®çã¯ãã¹ãä»¶æ°ãå¢ããããšã§ã¯ãªããéå»ã®äžå
·åãå±éºãªç¶æ
ãæ»ã£ããèªåã§æ€ç¥ã§ããããã«ããããšã§ãã
⢠ãã®ç¬¬1段éãããpytestãåãªããåäœç¢ºèªãã§ã¯ãªã**ãäºæ
鲿¢å°åž³ã**ãšããŠè²ãŠå§ããŸããã
ð° pytestãšã¯ïŒ
pytest ã¯ã
Pythonã§äœã£ãããã°ã©ã ããæ³å®ããéãã«åããŠããããèªåã§ç¢ºèªããããã®ãã¹ãããŒã«
ã§ãã
ããã¹ãããšèããšè©Šéšã®ããã«æãããããããŸãããããã®èšäºã§ã¯ã
人éãæ¯åæäœæ¥ã§ç¢ºèªããŠããããšããã³ãŒãã«èŠããŠããã£ãŠèªåç¹æ€ããä»çµã¿
ãããã«èãããšåãããããã§ãã
äŸãã°ã
å±éºãªHTML颚æååãå
¥ããŠã
HTMLãšããŠå®è¡ãããªããïŒ
å¿
èŠãªAIããã³ããã
ã¡ãããšGeminiãžæž¡ã£ãŠãããïŒ
éå»ã«çŽããXSS察çã
å°æ¥ã®ä¿®æ£ã§å
ã«æ»ã£ãŠããªããïŒ
ãšãã£ãããšããpytestãžç¢ºèªé ç®ãšããŠæžããŠãããŸãã
ãããŠpytestãå®è¡ãããšã
passed
ãªãã
ãã®ç¢ºèªé ç®ã¯çŸåšå®ãããŠãã
failed
ãªãã
æ³å®ããŠããæ¡ä»¶ãšéãç¶æ ã«ãªã£ãŠãã
ããšãåãããŸãã
ãã®èšäºã§ã¯ã
3 passed
â
9 passed
ãšpytestãå¢ããŠãããŸããã
æ°åãã®ãã®ãå¢ããããšãç®çã§ã¯ãããŸããã
ãäœä»¶ãããããããã
ãã®pytestããã©ããªäºæ ãäžå ·åãé²ãããã«ååšããŠããã®ã
ãéèŠããŠããŸãã
å°éçšèªãåºãŠããŸãããåããŠèªãæ¹ã§ãæµãã远ãããããã§ããã ããã®å Žã§èª¬æããŠãããŸãã
远èš
ãã®èšäºã¯ãpytestã3ä»¶ãã9ä»¶ãžåŒ·åããã第1段éãæç¹ã®èšé²ã§ãã
åœæãAIè¿ç衚瀺ã«ã¯
createTextNode()ãš<br>ãçµã¿åãããæ¹åŒã䜿çšããŠããŸããã
ãã®åŸãã³ã¡ã³ãã§ãææ¡ããã ããinnerTextãå®éã«æ€èšŒããä»åã®çšéã§ã¯HTMLãšããŠè§£éãããªãç¶æ ãšæ¹è¡è¡šç€ºãç¶æããªãããããç°¡æœã«å®è£ ã§ããããšã確èªãããããçŸåšã¯innerTextãå©çšããŠããŸããXSSååž°ãã¹ãã«ã€ããŠããçŸåšã®å®è£ ã«åãããŠ
innerTextãç¶æãããinnerHTMLãªã©ã®å±éºãªHTML sinkãžæ»ã£ãŠããªãããšã確èªããåœ¢ãžæŽæ°ããŠããŸãããã®ãããæ¬æäžã®
createTextNode()ãš<br>ã«é¢ããèšè¿°ã¯ã第1段é宿œæç¹ã®èšé²ãšããŠãèªã¿ãã ããã
pytest匷åã·ãªãŒãº
ã¯ããã«
çŸåœ¹ãã©ãã¯ãã©ã€ããŒãå人éçºäžã®Flaskã¢ããªã§ãCodexã䜿ããªããã»ãã¥ãªãã£ãä¿å®æ§ã®èŠçŽããé²ããŠããŸãã
ãããŸã§ã
- AIè¿ç衚瀺ã®XSS察ç
- åçã©ã³ãã³ã°è¡šç€ºã®ä¿ååXSS察ç
- 空DBããåææ§ç¯ã§ããªããã€ã°ã¬ãŒã·ã§ã³åé¡
ãªã©ãä¿®æ£ããŠããŸããã
ãã ãä¿®æ£ãé²ããäžã§äžã€æ°ã«ãªã£ãããšããããŸããã
çŸåšã®pytestãããŸãã«ãç°¡åã§ã¯ãªããïŒ
ãšããç¹ã§ãã
åœæã®pytestã¯3ä»¶ã ãã§ããã¹ãŠbuild_sales_prompt()ãšãã1ã€ã®é¢æ°ãã確èªããŠããŸããã§ããã
ããã§ä»åã¯ãpytestãåãªããåäœç¢ºèªãã§ã¯ãªãã
éå»ã«çºçããäžå ·åããã€ãªãããããäºåºŠãšåãç¶æ ãžæ»ããªãããã®ãäºæ 鲿¢å°åž³ã
ãšããŠè²ãŠãããšã«ããŸããã
ä»åã¯ãã®ç¬¬1段éãšããŠã
- GitHub Actionsã®pytestå šä»¶åéå
- XSSååž°ãã¹ã
- Jinja autoescapeååž°ãã¹ã
- ããã³ããå¥çŽãã¹ã
- Geminiãžã®ããã³ããæ¥ç¶ãã¹ã
ã远å ã»åŒ·åããŸããã
æ¹ååã®pytest
æ¹ååã«ååšããŠããpytestã¯ãtest_prompts.pyã®3ä»¶ã ãã§ããã
äž»ã«ç¢ºèªããŠããã®ã¯ã
- 販売ããŒã¿ãããã³ãããžå«ãŸããŠãã
- ãææ¡ã3ç¹æããŠããšããæèšããã
- æ»ãå€ãæååã§ãã
ãšãã£ãå 容ã§ãã
äžèŠãããšãã¹ããããããã«èŠããŸãã
ãããCodexã«éç調æ»ãäŸé Œãããšãããªã匱ãããšãåãããŸããã
äŸãã°ã極端ã«èšãã°æ¬¡ã®ãããªå®è£ ã§ãéãå¯èœæ§ããããŸãã
return sales_summary + " ææ¡ã3ç¹æããŠ ç®æ¡æžã3ç¹"
ããã§ãã
- å ¥åããŒã¿ãå«ãŸããŠãã
- åºå®æèšãå«ãŸããŠãã
- æ»ãå€ãæåå
ãšããæ¡ä»¶ã¯æºãããŠããŸããŸãã
æ¬æ¥ããã³ããã«å«ãŸããŠããã
- AIã®åœ¹å²
- åæèгç¹
- ææ¡æ°
- åç圢åŒ
- æç« é
ãªã©ãæ¶ããŠããŠãããã¹ãã¯æåããŸãã
ã€ãŸãã
ãã¹ããéã = æ¬æ¥ã®ä»æ§ãå®ãããŠãã
ãšã¯éããªãç¶æ ã§ããã
ããã«èŠã€ãã£ãCIåŽã®åé¡
調æ»äžãGitHub Actionsã«ãåé¡ãèŠã€ãããŸããã
åœæã®CIã§ã¯ã
pytest test_prompts.py -v
ãå®è¡ããŠããŸããã
ã€ãŸããä»åŸäŸãã°ã
test_security.py
test_sales.py
test_api.py
ã远å ããŠããGitHub Actionsã¯ããããå®è¡ããŸããã
ããŒã«ã«ã§ã¯ãã¹ãããŠããŠããCIã§ã¯çŽ éãããŠããŸããŸãã
ããã¯pytestããäºæ 鲿¢å°åž³ãã«ããããã§ããªã倧ããªåé¡ã§ãã
ããã§ã
pytest -v
ãžå€æŽããŸããã
ããã«ãããpytestã®éåžžã®ãã¹ãåéã«ãŒã«ã«åŸã£ãŠãæ°ãã远å ãããã¹ããã¡ã€ã«ãCIã§å®è¡ãããããã«ããŸããã
倿Žèªäœã¯1è¡ã ãã§ãã
- pytest test_prompts.py -v
+ pytest -v
ããããä»åŸã®ãã¹ãéçšãèãããšéèŠãªå€æŽã§ããã
ä»åã®æ¹é
ä»åã®ç®çã¯ã
ãã¹ãä»¶æ°ãå¢ããããš
ã§ã¯ãããŸããã
éå»ã«å®éã«èµ·ããäžå ·åããä¿®æ£ããè匱æ§ãã
å°æ¥åãç¶æ ãžæ»ã£ãæç¹ã§pytestã倱æããããš
ãç®æšã«ããŸããã
ãã®ãããä»åã¯æ¬äœæ©èœã倿Žããã
ãã§ã«ä¿®æ£æžã¿ã§ãæ£ããç¶æ ããåãã£ãŠãããã®ãååž°ãã¹ããšããŠåºå®ããŸããã
第1段éã§è¿œå ã»åŒ·åãããã¹ã
æçµçã«pytestã¯3ä»¶ãã9ä»¶ã«ãªããŸããã
1. 販売ããŒã¿ãæ£ããåºç»ã«å ¥ã£ãŠããã
test_build_sales_prompt_places_sales_data_in_its_section
åã«è²©å£²ããŒã¿ãæååå ã®ã©ããã«ååšããã ãã§ã¯ãªãã
æ¬æ¥ã®è²©å£²ããŒã¿åºç»ãžé 眮ãããŠããããš
ã確èªããŸãã
ããã«ãããããã³ããæ§é ãå£ããŠã以åã®ããã«èŠéãã«ãããªããŸãã
2. AIã®åœ¹å²ã»åæèгç¹ãå®ã
test_build_sales_prompt_preserves_role_and_analysis_contract
ããã³ããå ã«å¿ èŠãªã
- AIã®åœ¹å²
- åæã«å¿ èŠãªèŠç¹
ãªã©ãæ®ã£ãŠããããšã確èªããŸãã
以åã¯äžéšã®åºå®æèšã ãæ®ã£ãŠããã°éãå¯èœæ§ããããŸãããã
ä»åããã¯ããã³ããã®ã圹å²ãããåæèгç¹ããå®ãããã«ããŸããã
3. åºåæ¡ä»¶ãå®ã
test_build_sales_prompt_preserves_output_contract
Geminiãžæ±ããŠããã
- ææ¡æ°
- ç®æ¡æžã
- æç« é
- ç°¡æœã
ãªã©ã®åçæ¡ä»¶ãç¶æãããŠããããšã確èªããŸãã
å šæå®å šäžèŽã«ã¯ããŠããŸããã
å°ãæç« ã調æŽããã ãã§ãã¹ããå£ãããããªã
é床ã«èããã¹ã
ã«ããªãããã§ãã
éèŠãªå¥çŽåäœã§ç¢ºèªããŠããŸãã
Geminiãžæ¬åœã«ããã³ãããæž¡ã£ãŠããã
ä»å远å ããäžã§ãå人çã«éèŠã ãšæããã®ããã¡ãã§ãã
test_generate_ai_advice_sends_complete_sales_prompt
以åã¯ã
build_sales_prompt()
åäœãã確èªããŠããŸããã§ããã
ãããã颿°åäœãæ£åžžã§ãã
å®éã®GeminiåŒã³åºãã§ãã®é¢æ°ã«ãã£ãŠçµã¿ç«ãŠãå 容ã䜿ãããŠããªããã°æå³ããããŸããã
ããã§ä»åã¯ã
-
build_sales_prompt()ã§äœã£ãå 容ãGeminiãžæž¡ã - 䜿çšã¢ãã«ãèšå®å€ãšäžèŽãã
- Geminiã®è¿çããã¹ããæ»ã
ããšãŸã§ç¢ºèªããŸããã
Gemini APIã¯ã¢ãã¯ããŠå€éšéä¿¡ããªã
pytestãå®è¡ãããã³ã«å®éã®Gemini APIãžæ¥ç¶ããã®ã¯é¿ãããã§ãã
ããã§ã
unittest.mock.Mock
ã䜿çšããŠGemini Clientãã¢ãã¯ããŸããã
ãã¹ãçšã®ãããŒAPIããŒãèšå®ãã
genai.Client
ãMockãžå·®ãæ¿ããŠããŸãã
è¿çãã
SimpleNamespace(
text="ã¢ãã¯ãããAIã¢ããã€ã¹"
)
ã®ããã«åºå®ããŠããŸãã
ããã«ããã
- å®APIããŒäžèŠ
- å€éšéä¿¡ãªã
- Gemini APIãå®éã«åŒã³åºããªã
- ãããã¯ãŒã¯ç¶æ ã«å·Šå³ãããªã
ãã¹ãã«ãªããŸããã
XSSã®åçºé²æ¢ãã¹ã
ä»åç¹ã«éèŠããã®ãã
æè¿ä¿®æ£ããXSS察çãpytestãžæ®ãããš
ã§ãã
远å ãããã¹ãã¯ä»¥äžã§ãã
test_dynamic_ranking_product_name_uses_text_dom_api
test_dashboard_ai_responses_use_text_dom_api
test_input_ai_response_uses_text_dom_api
åçã©ã³ãã³ã°ã®ä¿ååXSS
以åãåååãåçã©ã³ãã³ã°ãžè¡šç€ºããéã«ã
innerHTML
ã䜿çšããŠããç®æããããŸããã
ä¿®æ£åŸã¯DOM APIãštextContentãå©çšãã圢ãžå€æŽããŠããŸãã
ä»åã®pytestã§ã¯ã
åååã衚瀺ããçµè·¯ãå°æ¥åã³å±éºãªHTML sinkãžæ»ããªãããã«ç¢ºèªããŸãã
AIè¿ç衚瀺ã®XSS
AIçµå¶ã¢ããã€ã¹ãšAIãããã€ã§ãã
以åã¯innerHTMLã䜿çšããŠããŸããã
第1段é宿œæç¹ã§ã¯ã
createTextNode()<br>- DOM API
ã䜿çšããAIè¿çãã®ãã®ãHTMLãšããŠè§£éãããªã衚瀺æ¹åŒãžå€æŽããŠããŸããã
pytestã§ã¯ããã®è¡šç€ºçµè·¯ãå°æ¥innerHTMLãªã©ãžæ»ããªãããšã確èªããsource guardã远å ããŸããã
ãªããèšäºå
¬éåŸã®è¿œå æ€èšŒãçµãŠãçŸåšã®å®è£
ã§ã¯innerTextãå©çšããŠããŸãã
çŸåšã®ååž°ãã¹ããå®è£
ã«åãããŠæŽæ°ããinnerTextã«ãã衚瀺ãç¶æãããŠããããšãšã察象çµè·¯ãžinnerHTMLã»outerHTMLã»insertAdjacentHTMLãªã©ãæ»ã£ãŠããªãããšã確èªãã圢ã«ãªã£ãŠããŸãã
ãinnerHTMLã1æåã§ããã£ãã倱æãã«ã¯ããªãã£ã
ããã¯å°ãæèããŸããã
äŸãã°ã
ãã¡ã€ã«å
ã«innerHTMLãšããæååãååšããã倱æ
ãšãããã¹ãã¯ç°¡åã«æžããŸãã
ããããããã§ã¯å°æ¥ã
å®å
šäžåé¡ã®ãªãå¥çšéã§innerHTMLã䜿ãå¿
èŠãåºãå Žåã§ããã¹ãã倱æããŸãã
ã€ãŸãã
é床ã«åºãããçŠæ¢ã«ãŒã«
ã«ãªããŸãã
ããã§ä»åã¯ã
- ååã©ã³ãã³ã°
- AIçµå¶ã¢ããã€ã¹
- AIãããã€
ãšããã
å®éã«éå»åé¡ã«ãªã£ãå€éšæååã®è¡šç€ºçµè·¯
ã ãã察象ã«ããŸããã
pytestã®ç®çã¯ã
ãinnerHTMLãšããèšèãçŠæ¢ããããšã
ã§ã¯ãªãã
éå»ãšåãå±éºãªç¶æ ãžæ»ãããšãé²ãããš
ã ããã§ãã
Jinjaã®autoescapeãååž°ãã¹ãå
AIè¿çã®åæè¡šç€ºã§ã¯ä»¥åã
| safe
ã䜿çšããŠããŸããã
ä¿®æ£åŸã¯åé€ããJinjaæ¬æ¥ã®autoescapeãå©çšããŠããŸãã
ããã§ã
test_dashboard_initial_ai_binding_does_not_disable_autoescape
ã远å ããŸããã
ããã¯ãã³ãã¬ãŒããœãŒã¹ã確èªãã
-
{{ ai_advice }}ã䜿ãããŠããããš -
| safeãæ»ã£ãŠããªãããš
ããã§ãã¯ããsource guardã§ãã
ããã«ãããå°æ¥ãŸãåæAI衚瀺ãžsafeæå®ãæ»ãäºæ
ãæ€ç¥ããããããŸããã
å®éã«HTML颚æååãJinjaã§æç»
ããã«ã
test_dashboard_initial_ai_advice_autoescapes_html_like_text
ã远å ããŸããã
äŸãã°ã
<b>ãã¹ã</b>
<img src=x>
ã®ãããªæååãJinjaãžæž¡ãã
ãããå®éã®bèŠçŽ ãimgèŠçŽ ãšããŠçæãããã
ãšã¹ã±ãŒããããæååãšããŠæ±ãããããš
ã確èªããŸãã
ãã¡ãã¯ãã³ãã¬ãŒããœãŒã¹ãèŠãã ãã§ã¯ãªãã
å®éã«Jinjaã§ãã³ãã¬ãŒããæç»ããBeautifulSoupã§çæãããHTMLã確èªãããã¹ãã§ãã
pytestçµæ
ãŸãã
pytest --collect-only -q
ãå®è¡ããŸããã
第1段é宿œæç¹ã®çµæã¯ã
9 tests collected in 8.23s
ãšãªããæ°ãã远å ãããã¹ãããã¹ãŠåéãããŸããã
次ã«ã
pytest -v
ãå®è¡ããŸããã
çµæã¯ã
9 passed in 6.37s
ã§ããã
- æåïŒ9ä»¶
- 倱æïŒ0ä»¶
- ã¹ãããïŒ0ä»¶
ãã¹ãŠæåããŸããã
ãã®9ä»¶ã¯ããããŸã§ç¬¬1段é宿œæç¹ã®ãã¹ãæ°ã§ãã
ãã®åŸããå®éã«èŠã€ãã£ãäžå ·åãå®ããã仿§ãååž°ãã¹ããšããŠè¿œå ããpytestã®æ€èšŒç¯å²ãåºããŠããŸãã
第1段éã§ã¯DBãDockerã䜿ã£ãŠããªã
第1段éã§ã¯è»œéãªååž°ãã¹ãã«éå®ããŸããã
ãã®ããã
- PostgreSQL
- Docker
- å®Gemini API
ã¯äœ¿çšããŠããŸããã
DBæäœããããŸããã
ä»åã¯ã
é«éãã€å€éšç°å¢ã«äŸåããªããã¹ã
ãå ã«æŽåããŸããã
倿Žãã¡ã€ã«
第1段éã§å€æŽããã®ã¯4ãã¡ã€ã«ã§ãã
.github/workflows/test.yml
test_prompts.py
test_ai_integration.py
test_xss_regressions.py
å·®åã¯ã
4 files changed, 195 insertions(+), 13 deletions(-)
ã§ããã
æ¬äœã³ãŒãã
app.py
prompts.py
models.py
templates/
migrations/
ãªã©ã¯ããã®ã³ãããã§ã¯å€æŽããŠããŸããã
æ¢åã®å®è£ ãå€ããã®ã§ã¯ãªãã
ãã§ã«ä¿®æ£ããç¶æ ããã¹ãã§åºå®ãã
ããšã«éäžããŸããã
commit
æçµç¢ºèªåŸã以äžã®ã³ããããäœæããŸããã
01d76e8 test: strengthen regression coverage
origin/mainãžpushããŠããŸãã
ä»ååŠãã ããš
1. ãã¹ãä»¶æ°ãå€ãããšããããäœãå®ããããéèŠ
以åã¯pytestã3ä»¶ãããŸããã
ããã3ä»¶ãšãã
ã»ãŒåã1颿°ããèŠãŠããŸããã§ããã
ãã¹ãä»¶æ°ã ããèŠãã°ã
3ä»¶ â 9ä»¶
ã§ãããä»åéèŠãªã®ã¯æ°åã§ã¯ãããŸããã
å®ããç¯å²ãã
ããã³ããã®ç°¡åãªæåå確èª
ããã
XSS
Jinja autoescape
ããã³ããå¥çŽ
Geminiãžã®æ¥ç¶
CIå
šä»¶åé
ãŸã§åºãã£ãããšã§ãã
2. ãHTTP 200ãªãOKãã§ã¯åŒ±ã
ä»åã®èª¿æ»ã§ã
åã«ã
HTTP 200
ãèŠãã ãã§ã¯åŒ±ãããšãæ¹ããŠåãããŸããã
ã¬ã¹ãã³ã¹ãæåããŠããŠãã
- DBãæå³ããç¶æ ã«ãªã£ãŠããªã
- HTMLãšããŠå±éºã«è¡šç€ºãããŠãã
- éè€ã¬ã³ãŒããå¢ããŠãã
ãšãã£ãåé¡ãæ®ãå¯èœæ§ããããŸãã
ä»åŸã¯ã
ã¬ã¹ãã³ã¹çµæã ãã§ã¯ãªãããã®åŸã®ç¶æ ãŸã§ç¢ºèªãã
ãã¹ããå¢ãããŠããå¿ èŠããããšèããŸããã
3. pytestã¯ãäºæ 鲿¢å°åž³ãã«ã§ãã
ä»åã®æ¹åã§äžçªå€§ããã£ãã®ã¯ã
pytestã«å¯ŸããèŠæ¹ãå€ãã£ãããšã§ãã
以åã¯ã
æ£åžžã«åããŠããã確èªãããã®
ãšããæèŠã匷ããããŸããã
ãããä»ã¯ã
éå»ã«èµ·ããäºæ ã»äžå ·åã»ãã€ãªããããèšé²ããåãç¶æ ãžæ»ã£ããèªåã§æ¢ããä»çµã¿
ãšããŠèããŠããŸãã
äŸãã°ã
XSSãçºèŠ
â
ä¿®æ£
â
ååž°ãã¹ãã远å
â
å°æ¥åãå±éºãªç¶æ
ãžæ»ã
â
pytest倱æ
â
CIãèµ€ããªã
ãšããæµãã§ãã
ãããªã人éãéå»ã®ä¿®æ£å 容ããã¹ãŠèŠããŠããªããŠãã
pytestã確èªé ç®ãšããŠæ®ããŠãããŸãã
ãäºåºŠãšåãããšãèµ·ãããªããã§ã¯ãªããåãç¶æ ã«ããªãã
æ®æ®µã®ä»äºã§ãã
äºæ ããã¹ãèµ·ããããšã
次ããæ°ãã€ããŸã
ã ãã§ã¯åçºé²æ¢ã«ãªããŸããã
ããã ããªããäººã®æ³šæåã«åã³é Œãããšã«ãªããŸãã
éèŠãªã®ã¯ã
äºåºŠãšåãå±éºãªç¶æ³ã»ç¶æ ã«ãªããªãããã«ã¯ã©ãããã
ã ãšèããŠããŸãã
ã·ã¹ãã éçºã§ãåãã§ããã
äŸãã°XSSãªãã
å±éºãªæååãå
¥åããªãããã«ãã
ã§ã¯ãªãã
å±éºãªHTML颚æååãæ¥ãŠã
HTMLãšããŠå®è¡ãããªãç¶æ
ã«ãã
å¿ èŠããããŸãã
ãããŠä»åã
ããã«ãã®å ãšããŠã
å®å
šãªå®è£
ãå°æ¥å£ãããpytestã§æ¢ãã
ãšãããŸã§ä»çµã¿ã«æ®ããŸããã
第1段é宿œæç¹ã§èããŠããæ¬¡ã®æ¹å
ãã®èšäºãæžãã第1段éã®æç¹ã§ã¯ã
å€éšAPIãDBãå¿ èŠãšããªã軜éãªååž°ãã¹ããäžå¿ã«åŒ·åããŸããã
äžæ¹ã§ããŸã å®ããŠããªãé åãšããŠã
- PostgreSQLã®ç©ºDBãã€ã°ã¬ãŒã·ã§ã³
- æ¢åDBãžã®ãã€ã°ã¬ãŒã·ã§ã³
- èªèšŒã»èªå¯
- CSRF
- äžæ£ãªå£²äžå ¥å
- ååã®è«çåé€ãšå±¥æŽä¿æ
- 忥売äžã®éè€é²æ¢
- Gemini APIã®429ã»503ã»äžè¬äŸå€
- APIã¬ã¹ãã³ã¹
- ããã·ã¥ããŒãéèš
ãªã©ãæ®ã£ãŠãããšèããŠããŸããã
ãã®åŸãããããäžåºŠã«å€æŽããã®ã§ã¯ãªãã
å±éºãªç¶æ ã1ã€æ±ºãã â å ã«ãã¹ããæžã â ä¿®æ£ãã â å šãã¹ãã確èªãã
ãšããå°ããªåäœã§ã段éçã«æ€èšŒç¯å²ãåºããŠããŸãã
ç¹ã«DBãæ±ããã¹ãã§ã¯ã
HTTPã¬ã¹ãã³ã¹ã ãã§ã¯ãªãã
äžæ£å ¥åãä¿å倱æã®ããšã«DBãã©ã®ç¶æ ã«ãªã£ãŠããã
ãŸã§ç¢ºèªããããšãéèŠããããã«ãªããŸããã
ãªããèªèšŒã»èªå¯ã»CSRFãªã©ã奿®µéã§æ±ãäºå®ã®é åããããŸãã
ãããã«
ä»åã®æ¹åã§ã
pytestã¯3ä»¶ãã9ä»¶ã«ãªããŸããã
ãã ããç®çã¯ãã¹ãæ°ãå¢ããããšã§ã¯ãããŸããã
ãããŸã§èŠã€ããå°ããªäžå ·åãè匱æ§ãã
äžã€ãã€åçºé²æ¢çãšããŠæ®ããŠããããš
ãç®çã§ãã
å°ããªäºæ ããã€ãªããããèŠã€ãããã
çºèŠ
â
åå 確èª
â
ä¿®æ£
â
pytestãžåçºé²æ¢ã«ãŒã«ã远å
â
CIã§èªå確èª
ãšããæµããç©ã¿éããŠãããŸãã
pytestãã
ãæ£åžžç¢ºèªã®éå ·ããããäºæ 鲿¢å°åž³ããžã
ãã®èšäºã¯ãã®ç¬¬1段éã®èšé²ã§ããã
ãã®åŸããã®èãæ¹ãããŒã¹ã«ããã¹ãã§å®ãç¯å²ãå°ããã€åºããŠããŸãã
ãŸããAIè¿ç衚瀺ã«ã€ããŠããèšäºå
¬éåŸã®ã³ã¡ã³ãããã£ããã«innerTextãšããå¥ã®å®è£
æ¹æ³ãæ€èšŒããŸããã
ææ¡è ã人ã§ãã£ãŠãAIã§ãã£ãŠãã
ãã®ãŸãŸæ¡çšããã®ã§ã¯ãªããèªåã®ç°å¢ã§æ€èšŒããçŸåšã®ä»æ§ã«åãã確èªããŠããæ¡çšãã
ãšããå§¿å¢ããä»åŸã®éçºã§ç¶ããŠãããããšæããŸãã
Zennã§ã¯ããã®ãšãèããŠããããšãæžããŸãã
ãã®èšäºã§ã¯ãå®éã«è¿œå ããpytestãååž°ãã¹ãã®å 容ãäžå¿ã«èšé²ããŸããã
Zennã§ã¯å°ãèŠç¹ãå€ããŠãã3 passedããèŠãŠå®å¿ããŠãããšããããããªãããã®GREENã¯äœãå®ã£ãŠãããã ããïŒããšçãå§ããã®ããšãããéçºäžã®èãæ¹ã®å€åãæ¯ãè¿ã£ãŠããŸãã
pytest匷åã·ãªãŒãº
