æéæ ã¯éèŠã§ããã察åŠããããã«é Œã¿ãŸããæŠãæ¹æ³ã¯ããã€ããããŸãããäž»ãªãã®ã¯æ¬¡ã®ãšããã§ãã
- ãªãªãŒã¹ãµã€ã¯ã«ã䜿çšããŠãã¢ããªã±ãŒã·ã§ã³ãããå°ããªè£œåã«åå²ããŸããã
- ãã¹ããã©ãããã«åŸã£ãŠè£œåããã¹ãã§ã³ãŒãã£ã³ã°ããŸãã
æåŸã®æ®µèœã¯ç§ã®èšäºã®ãããã¯ã§ããã
ãã©ãããã®ãã¹ã
ãåç¥ã®ãšããããã¹ããã©ãããã«ã¯ãåäœãã¹ããçµ±åãã¹ããe2eãã¹ãã®3ã€ã®ã¬ãã«ããããŸããå€ãã®äººã¯ãŠããããe2eã«ç²ŸéããŠãããšæãã®ã§ãçµ±åãã¹ãã«ã€ããŠè©³ãã説æããŸãã
çµ±åãã¹ãã®äžç°ãšããŠãUIãšã®å¯Ÿè©±ãéããŠã¢ããªã±ãŒã·ã§ã³å šäœã®åäœããã§ãã¯ããŸãããe2eãã¹ããšã®äž»ãªéãã¯ãå®éã«ãããã³ã°ãèŠæ±ããªãããšã§ããããã¯ãå°æ¥ã®e2eãã¹ãã®æ°ãæžããããã«ãåé¢ã«ãããã¹ãŠã®ã·ã¹ãã ã®çžäºäœçšã®ã¿ããã§ãã¯ããããã«è¡ãããŸãããµã€ãã¬ã¹
ã䜿çšããŠãçµ±åãã¹ããèšè¿°ããŸãããã®èšäºã§ã¯ãä»ã®ãã¬ãŒã ã¯ãŒã¯ãšã¯æ¯èŒããŸããããªãç§ãã¡ãããã§çµãã£ãã®ããè¿°ã¹ãã ãã§ãã
- éåžžã«è©³çŽ°ãªããã¥ã¡ã³ãã
- ãã¹ãã®ç°¡åãªãããã°ïŒCypressã«ã¯ããã®ããã®ç¹å¥ãªGUIãããããã¹ãã®ã¿ã€ã ãã©ãã«ã¹ããããå«ãŸããŠããŸãïŒã
çµ±åãã¹ãã®äœæçµéšããªããéåžžã«ç°¡åãªéå§ãå¿ èŠã ã£ãããããããã®ãã€ã³ãã¯ããŒã ã«ãšã£ãŠéèŠã§ããããã®èšäºã§ã¯ãç§ãã¡ããã©ã£ãŠããéãã©ã®ãã³ããåãããã«ã€ããŠè©±ããå®è£ ã®ã¬ã·ããå ±æããããšæããŸãã
éã®å§ãŸã
æåã¯ã1ã€ã®ã¢ããªã±ãŒã·ã§ã³ã§Angular Workspaceã䜿çšããŠã³ãŒããæŽçããŸããããµã€ãã¬ã¹ããã±ãŒãžãã€ã³ã¹ããŒã«ããåŸãæ§æãšãã¹ããå«ããµã€ãã¬ã¹ãã©ã«ããã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãã«è¡šç€ºãããããããã®ãªãã·ã§ã³ã§åæ¢ããŸãããã¢ããªã±ãŒã·ã§ã³ãå®è¡ãããã®äžã§ãã¹ããå®è¡ããããã«å¿ èŠãªããã±ãŒãžãpackage.jsonã§æºåããããšãããšã次ã®åé¡ãçºçããŸããã
- Index.htmlã«ã¯ãçµ±åãã¹ãã§ã¯äžèŠãªããã€ãã®ã¹ã¯ãªãããå«ãŸããŠããŸãã
- çµ±åãã¹ããå®è¡ããã«ã¯ãã¢ããªã±ãŒã·ã§ã³ãåãããµãŒããŒãå®è¡ãããŠããããšã確èªããå¿
èŠããããŸããã
index.htmlã®åé¡ã¯ãã«ã¹ã¿ã ã®index.htmlãæå®ããå¥åã®ã¢ã»ã³ããªæ§æïŒcypressãšåŒã¶ããšã«ããŸãããïŒã«ãã£ãŠè§£æ±ºãããŸããããããå®è£ ããæ¹æ³ïŒç§ãã¡ã¯ãangular.jsonã§ã¢ããªã±ãŒã·ã§ã³ã®æ§æãèŠã€ãããã«ãã»ã¯ã·ã§ã³ãéããããã«ãµã€ãã¬ã¹ã®åå¥ã®æ§æãè¿œå ãããã®æ§æãserve-modeã«æå®ããããšãå¿ããªãã§ãã ããã
ãã«ãã®æ§æäŸïŒ
"build": {
...
"configurations": {
⊠//
"cypress": {
"aot": true,
"index": "projects/main-app-integrations/src/fixtures/index.html",
"fileReplacements": [
{
"replace": "projects/main-app/src/environments/environment.ts",
"with": "projects/main-app/src/environments/environment.prod.ts"
}
]
}
}
}
ãµãŒããŒãšã®çµ±åïŒ
"serve": {
...
"configurations": {
⊠//
"cypress": {
"browserTarget": "main-app:build:cypress"
}
}
}
ã¡ã€ã³ããïŒãµã€ãã¬ã¹æ§æã®å Žåãaotã¢ã»ã³ããªãæå®ãããã¡ã€ã«ãç°å¢ã«çœ®ãæããŸããããã¯ããã¹ãäžã«prodã®ãããªã¢ã»ã³ããªãäœæããããã«å¿ èŠã§ãã
ãããã£ãŠãindex.htmlãèšç®ããŸãããã¢ããªã±ãŒã·ã§ã³ãçæãããã«ããå®äºãããŸã§åŸ æ©ããŠããã®äžã§ãã¹ããå®è¡ããŸãããããè¡ãã«ã¯ãstart-server-and-testã©ã€ãã©ãªã䜿çšããããã«åºã¥ããŠã¹ã¯ãªãããèšè¿°ããŸãã
"main-app:cy:run": "cypress run",
"main-app:cy:open": "cypress open",
"main-app:integrations": "start-server-and-test main-app:serve:cypress http://localhost:8808/app/user/ main-app:cy:run",
"main-app:integrations:open": "start-server-and-test main-app:serve:cypress http://localhost:8808/app/user/ main-app:cy:open"
ã芧ã®ãšãããã¹ã¯ãªããã«ã¯ããªãŒãã³ãšå®è¡ã®2çš®é¡ããããŸãããªãŒãã³ã¢ãŒãã¯ããµã€ãã¬ã¹èªäœã®GUIãéãããã¹ããåãæ¿ããŠã¿ã€ã ãã©ãã«ã䜿çšã§ããŸããå®è¡ã¢ãŒãã¯åãªããã¹ãå®è¡ã§ããããã®å®è¡ã®æçµçµæã§ãããCIã§ã®å®è¡ã«æé©ã§ãã
è¡ãããäœæ¥ã®çµæã«åºã¥ããŠãæåã®ãã¹ããäœæããŠCIã§å®è¡ããããã®éå§ãã¬ãŒã ã¯ãŒã¯ãååŸããããšãã§ããŸããã
åäžãªããžããª
説æãããŠããã¢ãããŒãã«ã¯éåžžã«é¡èãªåé¡ããããŸãããªããžããªã«2ã€ä»¥äžã®ã¢ããªã±ãŒã·ã§ã³ãããå Žåã1ã€ã®ãã©ã«ããŒã䜿çšããã¢ãããŒãã¯å®è¡ã§ããŸããããããŠãããã¯ç§ãã¡ã«èµ·ãããŸãããããããããã¯ããªãèå³æ·±ãæ¹æ³ã§èµ·ãããŸããããµã€ãã¬ã¹ã®å°å ¥åœæãç§ãã¡ã¯NXã«ç§»è¡ããŠããŸãããããã®ãã³ãµã ã§ãµã€ãã¬ã¹ãšã®é£æºãå¯èœã«ãªããŸããããã®äžã§ã®ä»äºã®ååã¯äœã§ããïŒ
- main-appã®ãããªã¢ããªã±ãŒã·ã§ã³ãããããã®æšªã«main-app-e2eã¢ããªã±ãŒã·ã§ã³ãäœæãããŸãã
- main-app-e2eã®ååãmain-app-integrationsã«å€æŽããŸã-ããªãã¯çŽ æŽãããã§ãã
ng e2e main-app-integrationsãšãã 1ã€ã®ã³ãã³ãã§çµ±åãã¹ããå®è¡ã§ããããã«ãªããŸãããNXã¯èªåçã«ã¡ã€ã³ã¢ããªãèµ·åããå¿çãåŸ ã¡ããã¹ããå®è¡ããŸãã
æ®å¿µãªãããçŸåšAngular Workspaceã䜿çšããŠãã人ãã¡ã¯å芳è ã®ãŸãŸã§ãããããã§ãåé¡ãããŸãããç§ã«ãã¬ã·ãããããŸããNXãšåæ§ã®ãã¡ã€ã«æ§é ã䜿çšããŸãã
- ã¢ããªã±ãŒã·ã§ã³ã®æšªã«main-app-integrationsãã©ã«ããŒãäœæããŸãã
- ãã®äžã«srcãã©ã«ããŒãäœæããããã«cypressãã©ã«ããŒã®å
容ãè¿œå ããŸãã
- cypress.jsonïŒæåã¯ã«ãŒãã«è¡šç€ºãããŸãïŒãmain-app-integrationsãã©ã«ããŒã«ç§»åããããšãå¿ããªãã§ãã ããã
- ãã¹ãããã©ã°ã€ã³ãããã³è£å©ã³ãã³ãïŒãã©ã¡ãŒã¿ãŒIntegrationFolderãpluginsFileãããã³supportFileïŒã䜿çšããŠãæ°ãããã©ã«ããŒãžã®ãã¹ãæå®ããŠãcypress.jsonãç·šéããŸãã
- ãµã€ãã¬ã¹ã¯ä»»æã®ãã©ã«ãå
ã®ãã¹ããåŠçã§ããŸãã
ãããžã§ã¯ããã©ã¡ãŒã¿ã䜿çšããŠãã©ã«ããæå®ãããããã³ãã³ããcypress run / openããcypress run / open -âproject ./projects/main-app-integrations/srcã«å€æŽããŸãã
Angular Workspaceã®ãœãªã¥ãŒã·ã§ã³ã¯ããã©ã«ããŒãæåã§äœæããããããã¢ããªããžããªå ã®ãããžã§ã¯ãã®1ã€ã§ã¯ãªãããšãé€ããŠãNXã®ãœãªã¥ãŒã·ã§ã³ã«ã§ããã ã䌌ãŠããŸãããŸãã¯ããµã€ãã¬ã¹ã®NXãã«ããŒãçŽæ¥äœ¿çšããããšãã§ããŸãïŒãµã€ãã¬ã¹ã䜿çšããNXäžã®ãªããžããªã®äŸã§ã¯ãnx-cypressãã«ããŒã®æçµçãªäœ¿çšæ¹æ³ã確èªã§ããŸã-angular.jsonãš
cart-e2eããã³products-e2eãããžã§ã¯ãã«æ³šç®ããŠãã ããïŒã
èŠèŠååž°
æåã®5ã€ã®ãã¹ãã®åŸãå®éã«ã¯ããã«ã¯ãã¹ãŠã®å¯èœæ§ããããããã¹ã¯ãªãŒã³ã·ã§ãããã¹ãã«ã€ããŠèããŸããã ãã¹ã¯ãªãŒã³ã·ã§ãããã¹ãããšããèšèã¯ãããŒã å ã§å€ãã®èŠçãåŒãèµ·ãããšåãã£ãŠèšã£ãŠãããŸããå®å®ãããã¹ããååŸããæ¹æ³ã¯ãæãç°¡åãªæ¹æ³ã§ã¯ãªãã£ãããã§ãã次ã«ãçºçããäž»ãªåé¡ãšãã®è§£æ±ºçã«ã€ããŠèª¬æããŸããcypress-image-snapshot
ã©ã€ãã©ãªããœãªã¥ãŒã·ã§ã³ãšããŠæ¡çšãããŸãããå®è£ ã«ã¯ããã»ã©æéã¯ããããŸããã§ããã20ååŸã«ããµã€ãºã1000Ã600ãã¯ã»ã«ã®ã¢ããªã±ãŒã·ã§ã³ã®æåã®ã¹ã¯ãªãŒã³ã·ã§ãããåãåããŸãããçµ±åãšäœ¿çšãåçŽããããããå€ãã®åã³ããããŸããã
5ã€ã®åç §ã¹ã¯ãªãŒã³ã·ã§ãããçæããåŸãCIã§ãã¹ããéå§ããçµæããã«ãããã©ãã©ã«ãªããŸãããopenã³ãã³ããšrunã³ãã³ãã䜿çšããŠäœæãããã¹ã¯ãªãŒã³ã·ã§ããã¯ç°ãªãããšãããããŸããã解決çã¯éåžžã«ã·ã³ãã«ã§ããïŒCIã¢ãŒãã§ã®ã¿ã¹ã¯ãªãŒã³ã·ã§ãããæ®ãã®ã§ãããšãã°æ¬¡ã®ããã«ãããŒã«ã«ã¢ãŒãã§ã¹ã¯ãªãŒã³ã·ã§ãããåé€ããŸããã
Cypress.Commands.overwrite(
'matchImageSnapshot',
(originalFn, subject, fileName, options) => {
if (Cypress.env('ci')) {
return originalFn(subject, fileName, options);
}
return subject;
},
);
ãã®ãœãªã¥ãŒã·ã§ã³ã§ã¯ããµã€ãã¬ã¹ã®envãã©ã¡ãŒã¿ãŒã確èªããŸããããŸããŸãªæ¹æ³ã§èšå®ã§ããŸãã
æžäœ
ããŒã«ã«ã§ã¯ããã¹ãã¯åèµ·åã«åæ Œãå§ããCIã§å床å®è¡ããããšããŸããçµæã¯ä»¥äžã®ãã
ã«ãªããŸããdiffã¹ã¯ãªãŒã³ã·ã§ããã§ãã©ã³ãã®éãã«æ°ã¥ãã®ã¯éåžžã«ç°¡åã§ããåç §ã¹ã¯ãªãŒã³ã·ã§ãããmacOSã§çæãããLinuxãCIã®ãšãŒãžã§ã³ãã«ã€ã³ã¹ããŒã«ãããŸããã
ééã£ã決å®
ãã¯ã»ã«ããšã®æå°ã®å·®å
ãäžããæšæºãã©ã³ãïŒUbuntuãã©ã³ããªã©ïŒã®1ã€ãéžã³ããã®ãã©ã³ããããã¹ããããã¯ã«é©çšããŸããïŒindex.htmlã§äœæããããµã€ãã¬ã¹ãã¹ãã®ã¿ãç®çãšããŠããŸãïŒã次ã«ãå šäœã®å·®åã0.05ïŒ ã«ããã¯ã»ã«ããšã®å·®åã20ïŒ ã«å¢ãããŸããããããã®ãã©ã¡ãŒã¿ãŒã䜿çšããŠãã³ã³ããŒãã³ãã®ããã¹ããå€æŽããå¿ èŠããã£ããšããŸã§ã1é±éãè²»ãããŸããããã®çµæãã¹ã¯ãªãŒã³ã·ã§ãããæŽæ°ããŠããŸãããããã«ãã¯ç·è²ã®ãŸãŸã§ãããçŸåšã®ãœãªã¥ãŒã·ã§ã³ã¯åœ¹ã«ç«ããªãããšã蚌æãããŠããŸãã
æ£ãã解決ç
å ã®åé¡ã¯ããŸããŸãªç°å¢ã«ãããŸãããååãšããŠã解決çã¯ããèªäœã瀺åããŠããŸã-Dockerããµã€ãã¬ã¹ã¯ãã§ã«ãããã³ã°ã€ã¡ãŒãžãæºåããŠããŸãã Cypressã¯ãã§ã«ã€ã¡ãŒãžã«å«ãŸããŠããããµã€ãã¬ã¹ãã€ããªãæ¯åããŠã³ããŒãããŠè§£åããªããããç»åã«ã¯ããŸããŸãªããªãšãŒã·ã§ã³ããããŸãïŒãµã€ãã¬ã¹GUIã¯ãã€ããªãã¡ã€ã«ãä»ããŠå®è¡ãããããŠã³ããŒããšè§£åã¯ããŠã³ããŒããããæéãããããŸãDockerã€ã¡ãŒãžïŒã
å«ãŸããŠããDockerã€ã¡ãŒãžã«åºã¥ããŠãç¬èªã®Dockerã³ã³ãããŒãäœæããŸããããã®ããã«ãåæ§ã®å 容ã®Integration-tests.Dockerfileãã¡ã€ã«ãäœæããŸããã
FROM cypress:included:4.3.0
COPY package.json /app/
COPY package-lock.json app/
WORKDIR /app
RUN npm ci
COPY / /app/
ENTRYPOINT []
ENTRYPOINTã®ãŒãåã«æ³šæããããšæããŸããããã¯ãããã©ã«ãã§cypress /å«ãŸããŠããã€ã¡ãŒãžã«èšå®ãããŠãããcypress runã³ãã³ãããã€ã³ãããŠãããããä»ã®ã³ãã³ãã䜿çšã§ããªãããã§ãããŸããdockerfileãã¬ã€ã€ãŒã«åå²ããŠããã¹ããåéãããã³ã«npm ciãåå®è¡ããªãããã«ããŸãã
ãªããžããªã®ã«ãŒãã«.dockerignoreãã¡ã€ã«ãè¿œå ãïŒããã§ãªãå ŽåïŒãnode-modules /ããã³* / node-modules /ãæå®ããå¿ èŠããããŸãã
Dockerã§ãã¹ããå®è¡ããããã«ã次ã®å 容ã§bashã¹ã¯ãªããintegration-tests.shãèšè¿°ããŸãã
docker build -t integrations -f integration-tests.Dockerfile .
docker run --rm -v $PWD/projects/main-app-integrations/src:/app/projects/main-app-integrations/src integrations:latest npm run main-app:integrations
ç°¡åãªèª¬æïŒIntegration-tests.Dockerfile Dockerã³ã³ãããŒãäœæããããªã¥ãŒã ãtestsãã©ã«ããŒã«ãã€ã³ãããŠãçæãããã¹ã¯ãªãŒã³ã·ã§ãããDockerããååŸã§ããããã«ããŸãã
åã³ãã©ã³ã
åã®ç« ã§èª¬æããåé¡ã解決ããåŸããã«ãã«èœã¡èŸŒã¿ããããŸããããçŽ1æ¥åŸã次ã®åé¡ãçºçããŸããïŒå·Šãšå³-ç°ãªãæç¹ã§ååŸããã1ã€ã®ã³ã³ããŒãã³ãã®ã¹ã¯ãªãŒã³ã·ã§ããïŒïŒ
ãããã¢ããã«ååãªã¿ã€ãã«ããªãããšã«æã泚æããŠãããšæããŸã... ãã®çç±ã¯éåžžã«åçŽã§ã-ãã©ã³ãã¯ã¢ã»ãããä»ããŠæ¥ç¶ãããŠããªãã£ããããCDNäžã«ãã£ããããããŒãã§ããŸããã§ããã
ééã£ã決å®
CDNãããã©ã³ããããŠã³ããŒããããµã€ãã¬ã¹æ§æçšã®ã¢ã»ããã«ããããã
ãçµ±åãã¹ãã®ããã«ã«ã¹ã¿ã index.htmlã§ããããæ¥ç¶ããŸãããã®æ±ºå®ã«ãããäŒç€Ÿã®ãã©ã³ããå€æŽãããŸã§ãç§ãã¡ã¯ãŸãšããªæéãéãããŸãããåãç©èªãããäžåºŠãã¬ã€ããããªãã£ãã
æ£ãã解決ç
ãµã€ãã¬ã¹æ§æçšã®index.html㧠ãã¹ãã«å¿ èŠãªãã¹ãŠã®ãã©ã³ãã®ããªããŒããéå§ããããšã決å®ãããŸãããããã¯æ¬¡ã®ããã«ãªããŸãã
<link
rel="preload"
href="...."
as="font"
type="font/woff2"
crossorigin="anonymous"
/>
ããŒãããæéããªãã£ããã©ã³ããåå ã§ãã¹ãã¯ã©ãã·ã¥ã®æ°ãæå°ã«ãªããŸãããããŒãã«ã¯ãªããŸããã§ãããããã§ãããã©ã³ããããŒãããæéããªãã£ãå ŽåããããŸãããµã€ãã¬ã¹èªäœã®KitchenSinkããã®è§£æ±ºçãæãã«ãªããŸãã-waitForResourceã
ä»åã®ã±ãŒã¹ã§ã¯ããã©ã³ãã®ããªããŒãããã§ã«æ¥ç¶ãããŠããããããµã€ãã¬ã¹ã§åã«visitã³ãã³ããåå®çŸ©ããŸããããã®çµæãããŒãžã«ç§»åããã ãã§ãªããæå®ããããã©ã³ããããŒãããããŸã§åŸ æ©ããŸãããŸããwaitForResourceããã©ã³ãã ãã§ãªããããŒããããéçèŠçŽ ïŒããšãã°ãç»åïŒã®åé¡ã解決ããããšãè¿œå ããããšæããŸãïŒãã®ãããã¹ã¯ãªãŒã³ã·ã§ãããå£ããŠããŠãwaitForResourceã倧ãã«åœ¹ç«ã¡ãŸããïŒããã®ãœãªã¥ãŒã·ã§ã³ãé©çšããåŸããã©ã³ããšããŒãã®éçèŠçŽ ã«åé¡ã¯ãããŸããã§ããã
ã¢ãã¡ãŒã·ã§ã³
ç§ãã¡ã®é çã¯ã¢ãã¡ãŒã·ã§ã³ã«é¢é£ããŠãããããã¯ä»æ¥ãŸã§ç¶ããŠããŸããããæç¹ã§ãèŠçŽ ã®ã¹ã¯ãªãŒã³ã·ã§ããã衚瀺ããå§ããããã¢ãã¡ãŒã·ã§ã³ãå§ãŸãåã«ã¹ã¯ãªãŒã³ã·ã§ãããæ®ãããŸãããã®ãããªã¹ã¯ãªãŒã³ã·ã§ããã¯äžå®å®ã§ãããæšæºãšã®æ¬¡ã®æ¯èŒããšã«éãããããŸããã§ã¯ãã¢ãã¡ãŒã·ã§ã³ã«é¢é£ããåé¡ã解決ãããšãã«ãç§ãã¡ã¯ã©ã¡ãã«é²ãã ã®ã§ããããã
æåã®è§£æ±ºç
æåã®æ®µéã§é ã«æµ®ããã æãç°¡åãªããšã¯ãã¹ã¯ãªãŒã³ã·ã§ãããäœæããåã«ããã©ãŠã¶ãäžå®æéåæ¢ããŠãã¢ãã¡ãŒã·ã§ã³ãå®äºããæéã確ä¿ããããšã§ãã100msã200msã500msããããŠçµæãšããŠ1000msã®ãã§ãŒã³ã«æ²¿ã£ãŠé²ã¿ãŸãããæ¯ãè¿ã£ãŠã¿ããšããã®æ±ºå®ã¯åœåã²ã©ããã®ã ã£ããšç解ããŠããŸãããåã決å®ã«å¯ŸããŠããªãã«èŠåãããã£ãã ãã§ãããªãã²ã©ãïŒã¢ãã¡ãŒã·ã§ã³ã®æéã¯ç°ãªããCIã®ãšãŒãžã§ã³ããæã éããªãããšããããŸãããã®ãããããŒãžãå®å®ãããŸã§ã®åŸ æ©æéãæã ç°ãªã£ãŠããŸããã
第äºã®è§£æ±ºç
1ç§åŸ æ©ããŠããããŒãžã¯åžžã«å®å®ããããšãã§ããŸããã§ãããå°ã調ã¹ããšãããAngular- Testabilityã®ããŒã«ãèŠã€ãããŸãããååã¯ãZoneJSã®å®å®æ§ã®è¿œè·¡ã«åºã¥ããŠããŸãã
Cypress.Commands.add('waitStableState', () => {
return cy.window().then(window => {
const [testability]: [Testability] = window.getAllAngularTestabilities();
return new Cypress.Promise(resolve => {
testability.whenStable(() => {
resolve();
}, 3000);
});
});
});
ãããã£ãŠãã¹ã¯ãªãŒã³ã·ã§ãããäœæãããšãã«ãcy.waitïŒ1000ïŒãšcy.waitStableStateïŒïŒã®2ã€ã®ã³ãã³ããåŒã³åºããŸããã
ãã以æ¥ãã©ã³ãã ã«ãããããããã¹ã¯ãªãŒã³ã·ã§ããã¯1ã€ããããŸããããã¢ã€ãã«ç¶æ ã®ãã©ãŠã¶ãŒã§è²»ããããæéãåèšããŠã¿ãŸãããããã¹ãã«5ã€ã®ã¹ã¯ãªãŒã³ã·ã§ããããããšããŸããããããã«1ç§ã®å®å®ããåŸ æ©æéãšã©ã³ãã ãªæéããããŸããããšãã°ãå¹³å1.5ç§ãšããŸãããïŒå®éã«ã¯å¹³åã枬å®ããŠããªãã£ãã®ã§ãèªåã®ææ ã«å¿ããŠé ããåã£ãŠããŸãïŒã ...ãã®çµæããã¹ãã§ã¹ã¯ãªãŒã³ã·ã§ãããäœæããã®ã«ããã«12.5ç§ããããŸãããã§ã«20ã®ãã¹ãã·ããªãªãäœæããŠããŠãåãã¹ãã«å°ãªããšã5ã€ã®ã¹ã¯ãªãŒã³ã·ã§ãããå«ãŸããŠãããšããŸããå®å®æ§ã®ããã®è¶ éæ¯æãã¯ãå©çšå¯èœãª20ã®ãã¹ãã§çŽ4åã§ããããšãããããŸãã
ãããããããæ倧ã®åé¡ã§ã¯ãããŸãããäžèšã§èª¬æããããã«ãããŒã«ã«ã§ãã¹ããå®è¡ããå Žåãã¹ã¯ãªãŒã³ã·ã§ããã¯è¿œè·¡ãããŸããããCIã§ã¯è¿œè·¡ãããŸããæåŸ ã®ããããããŠã³ã¹æéãªã©ã®ã³ãŒãã®ã³ãŒã«ããã¯ã¯ãã¹ã¯ãªãŒã³ã·ã§ããããšã«ããªã¬ãŒãããŸãããããã¯ãCIãšããŒã«ã«ã§ãã§ã«ã©ã³ãã åãããŠããããã§ããããŸããŸãªæ¹æ³ã§æž¡ãããŸãã
çŸåšã®ãœãªã¥ãŒã·ã§ã³
Angularã¢ãã¡ãŒã·ã§ã³ããå§ããŸããããDOMèŠçŽ ã®ã¢ãã¡ãŒã·ã§ã³äžã®ãæ°ã«å ¥ãã®ãã¬ãŒã ã¯ãŒã¯ã¯ãng-animatingã¯ã©ã¹ããã³ã°ãããŸããããããœãªã¥ãŒã·ã§ã³ã®éµã§ããããªããªããä»ã¯èŠçŽ ã«ã¢ãã¡ãŒã·ã§ã³ã¯ã©ã¹ããªãããšã確èªããå¿ èŠãããããã§ãããã®çµæã次ã®ãããªé¢æ°ãäœæãããŸããã
export function waitAnimation(element: Chainable<JQuery>): Chainable<JQuery> {
return element.should('be.visible').should('not.have.class', 'ng-animating');
}
è€éãªããšã¯ãªãããã§ããããããç§ãã¡ã®æ±ºå®ã®åºç€ãšãªã£ããã®ã§ãããã®ã¢ãããŒãã§æ³šæãããããšïŒã¹ã¯ãªãŒã³ã·ã§ãããäœæãããšãã¯ãã¹ã¯ãªãŒã³ã·ã§ãããäžå®å®ã«ããèŠçŽ ã®ã¢ãã¡ãŒã·ã§ã³ãç解ããå¿ èŠããããŸããã¹ã¯ãªãŒã³ã·ã§ãããäœæããåã«ãèŠçŽ ãã¢ãã¡ãŒã·ã§ã³åãããŠããªãããšã確èªããã¢ãµãŒã·ã§ã³ãè¿œå ããŸãããã ããã¢ãã¡ãŒã·ã§ã³ãCSSã«å«ããããšãã§ããŸãããµã€ãã¬ã¹èªäœãèšãããã«ãèŠçŽ ã®ãã¹ãŠã®ã¢ãµãŒã·ã§ã³ã¯ã¢ãã¡ãŒã·ã§ã³ãçµäºããã®ãåŸ ã£ãŠããŸã-詳现ã¯ãããšããã§ãã€ãŸããã¢ãããŒãã®æ¬è³ªã¯æ¬¡ã®ãšããã§ããã¢ãã¡ãŒã·ã§ã³åãããèŠçŽ ããããããã«ã¢ãµãŒã·ã§ã³ãè¿œå ããŸã-shouldïŒ 'be.visible'ïŒ/ shouldïŒ 'not.be.visible'ïŒ-ãããŠããµã€ãã¬ã¹èªäœã¯ã¢ãã¡ãŒã·ã§ã³ãèŠçŽ ã§çµäºããã®ãåŸ ã¡ãŸãïŒãããããng-animatingã«ãããœãªã¥ãŒã·ã§ã³ã¯å¿ èŠãªãããµã€ãã¬ã¹ãã§ãã¯ã ãã§ååã§ãããä»ã®ãšããã¯waitAnimationãŠãŒãã£ãªãã£ã䜿çšããŠããŸãïŒã
ããã¥ã¡ã³ãèªäœã«èšèŒãããŠããããã«ããµã€ãã¬ã¹ã¯ããŒãžäžã®èŠçŽ ã®äœçœ®ã®å€æŽããã§ãã¯ããŸãããäœçœ®ã®å€æŽã«é¢ãããã¹ãŠã®ã¢ãã¡ãŒã·ã§ã³ã§ã¯ãªããfadeIn / fadeOutã¢ãã¡ãŒã·ã§ã³ããããŸãããããã®å Žåã§ãã解決ã®ååã¯åãã§ããèŠçŽ ãããŒãžã«è¡šç€ºããããã©ããã確èªãããŸãã
cy.waitïŒ1000ïŒ+ cy.waitStableStateïŒïŒããwaitAnimationãšãµã€ãã¬ã¹ã¢ãµãŒã·ã§ã³ã«ç§»åããå Žåãå€ãã¹ã¯ãªãŒã³ã·ã§ãããå®å®ãããããã«çŽ2æéãè²»ããå¿ èŠããããŸããããçµæãšããŠããã¹ãå®è¡æéã¯+4åã§ã¯ãªã+ 20-30ç§ã«ãªããŸããã ãçŸæç¹ã§ã¯ãã¹ã¯ãªãŒã³ã·ã§ããã®ã¬ãã¥ãŒã«æ éã«åãçµãã§ããŸããDOMèŠçŽ ã®ã¢ãã¡ãŒã·ã§ã³äžã«ã¹ã¯ãªãŒã³ã·ã§ãããå®è¡ãããªãã£ãããšã確èªããã¢ãã¡ãŒã·ã§ã³ãåŸ ã€ãã¹ãã«ãã§ãã¯ãè¿œå ããŸãããããšãã°ãããŒã¿ãèªã¿èŸŒãŸãããŸã§ãããŒãžã«ãã¹ã±ã«ãã³ã衚瀺ãè¿œå ããããšããããããŸãããããã£ãŠãã¹ã¯ãªãŒã³ã·ã§ãããäœæããå Žåããã§ãŒãã¢ãã¡ãŒã·ã§ã³ãååšãããããDOMã«ã¹ã±ã«ãã³ãååšããŠã¯ãªããªããšããèŠä»¶ãããã«ã¬ãã¥ãŒã«å±ããŸãã
ãã®ã¢ãããŒãã®åé¡ã¯1ã€ã§ããã¹ã¯ãªãŒã³ã·ã§ãããäœæãããšãã«åžžã«ãã¹ãŠãäºæž¬ã§ãããšã¯éãããCIã«åé¡ãããå¯èœæ§ããããŸããããã«å¯ŸåŠããæ¹æ³ã¯1ã€ã ãã§ã-ãã®ãããªã¹ã¯ãªãŒã³ã·ã§ããã®äœæãããã«ç·šéããŠã延æããããšã¯ã§ããŸãããããããªããšãéªã ããŸã®ããã«èç©ãããæçµçã«ã¯çµ±åãã¹ãããªãã«ããŸãã
ã¹ã¯ãªãŒã³ã·ã§ããã®ãµã€ãº
ã¹ã¯ãªãŒã³ã·ã§ããã®ããã©ã«ãã®è§£å床ã¯1000Ã600ãã¯ã»ã«ã§ããæ®å¿µãªãããDockerã§å®è¡ããŠãããšãã®ãã©ãŠã¶ãŒãŠã£ã³ããŠã®ãµã€ãºã«åé¡ããããŸãããµã€ãã¬ã¹ã§ãã¥ãŒããŒãã®ãµã€ãºãå€æŽããŠãã圹ã«ç«ã¡ãŸãããChromeãã©ãŠã¶ãŒã®è§£æ±ºçãèŠã€ããŸããïŒElectronã§ã¯ãæå¹ãªè§£æ±ºçãããã«èŠã€ããããšã¯ã§ããŸããã§ãããããã®åé¡ã§ææ¡ããã解決çã¯éå§ããŸããã§ããïŒããŸããChromeã§ãã¹ããå®è¡ããããã«ãã©ãŠã¶ãå€æŽããå¿ èŠããããŸãã
- NXã§ã¯ãªãããµã€ãã¬ã¹ã®open / runã³ãã³ããéå§ãããšãã«--browser chromeåŒæ°ã䜿çšããŠå®è¡ããrunã³ãã³ãã«ã¯--headlessãã©ã¡ãŒã¿ãæå®ããŸãã
- NXã®å Žåããã¹ããå«ãangular.jsonã®ãããžã§ã¯ãæ§æã§ã¯browserïŒchromeãã©ã¡ãŒã¿ãŒãæå®ããCIã§å®è¡ãããæ§æã«ã¯headlessïŒtrueãæå®ããŸãã
次ã«ããã©ã°ã€ã³ãç·šéããŠã1440Ã900ãã¯ã»ã«ã®ãµã€ãºã®ã¹ã¯ãªãŒã³ã·ã§ãããååŸããŸãã
module.exports = (on, config) => {
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--disable-dev-shm-usage');
launchOptions.args.push('--window-size=1440,1200');
return launchOptions;
}
return launchOptions;
});
};
æ¥ä»
ããã§ã¯ãã¹ãŠãåçŽã§ããçŸåšã®æ¥ä»ã«é¢é£ä»ããããŠããæ¥ä»ãã©ããã«è¡šç€ºãããŠããå Žåãä»æ¥ã®ã¹ã¯ãªãŒã³ã·ã§ããã¯ææ¥ã«ãªããŸããFiximã¯ç°¡åã§ãïŒ
cy.clock(new Date(2025, 11, 22, 0).getTime(), ['Date']);
ä»ã¿ã€ããŒãã¹ã¯ãªãŒã³ã·ã§ãããäœæãããšãã«ããã©ãã¯ã¢ãŠããªãã·ã§ã³ãæ°ã«ãã䜿çšããŸãããããšãã°ã
cy.matchImageSnapshot('salary_signing-several-payments', {
blackout: ['.timer'],
});
äžå®å®ãªãã¹ã
äžèšã®æšå¥šäºé ã䜿çšãããšããã¹ãã¯ã³ãŒãã ãã§ãªãããã¹ããå®è¡ãããç°å¢ã«ã圱é¿ãåããããã100ïŒ ã§ã¯ãªãæ倧ã®ãã¹ãå®å®æ§ãå®çŸã§ããŸãã
ãã®çµæãããšãã°ãCIã§ã®ãšãŒãžã§ã³ãã®ããã©ãŒãã³ã¹ã®äœäžãåå ã§ãç¹å®ã®å²åã®ãã¹ãã倱æããããšããããŸãããŸãããã¹ããå®å®ãããŸããã¹ã¯ãªãŒã³ã·ã§ãããæ®ãåã«å¿ èŠãªã¢ãµãŒã·ã§ã³ãè¿œå ããŸããããã®ãããªãã¹ãã修埩ããŠããéã¯ãcypress-plugin-retriesã䜿çšããŠå€±æãããã¹ããåè©Šè¡ã§ããŸãã
CIããã³ãããŸã
åã®ç« ã§ã¯ã1ã€ã®ã³ãã³ãã§ãã¹ããå®è¡ããæ¹æ³ãšãã¹ã¯ãªãŒã³ã·ã§ãããã¹ãã®æäœã«ã€ããŠåŠã³ãŸãããããã§ãCIæé©åã®æ¹åãèŠãããšãã§ããŸããç§ãã¡ã®ãã«ãã§ã¯ç¢ºå®ã«å®è¡ãããŸãïŒ
- NPM CIããŒã
- ã¢ããªã±ãŒã·ã§ã³ãaotã¢ãŒãã§çºçãããŸãã
- çµ±åãã¹ãã®å®è¡ã
æåãš2çªç®ã®ãã€ã³ããèŠãŠãCIã®ä»ã®ãã«ãïŒã¢ããªã±ãŒã·ã§ã³ã¢ã»ã³ããªã䜿çšãããã«ãïŒã§ãåæ§ã®æé ãå®è¡ãããããšãç解ããŸãããã
äž»ãªéãã¯ãng serveãå®è¡ããã®ã§ã¯ãªããng buildãå®è¡ããããšã§ãããããã£ãŠãçµ±åãã¹ããå«ããã«ãã§æ¢ã«ã¢ã»ã³ãã«ãããã¢ããªã±ãŒã·ã§ã³ãååŸããããã䜿çšããŠãµãŒããŒãäžããããšãã§ããã°ããã¹ããå«ããã«ãã®å®è¡æéãççž®ã§ããŸãã
ãªããããå¿ èŠã ã£ãã®ã§ããïŒç§ãã¡ã®ã¢ããªã±ãŒã·ã§ã³ã倧ãããå å®ããŠããã ãã§ã
CIå ã®ãšãŒãžã§ã³ãã§npm ci + npmãaotã¢ãŒãã§éå§ããã«ã¯ãçŽ15åããããŸãããããã«ã¯ãååãšããŠããšãŒãžã§ã³ãã«ããå€å€§ãªåŽåãå¿ èŠã§ãããããã«å ããŠçµ±åãã¹ããå®è¡ãããŸããããã§ã«20以äžã®ãã¹ããäœæããŠããŠã19æ¥ã®ãã¹ãã§ããã¹ããå®è¡ããããã©ãŠã¶ãŒããšãŒãžã§ã³ãã®è² è·ãé«ãããã«ã¯ã©ãã·ã¥ãããšããŸãããç解ã®ãšããããã«ããåéãããšãäŸåé¢ä¿ã®ã€ã³ã¹ããŒã«ãšã¢ããªã±ãŒã·ã§ã³ã®èµ·åãåã³åŸ æ©ããŸãã
ããããã¯ãã¢ããªã±ãŒã·ã§ã³åŽã®ã¹ã¯ãªããã«ã€ããŠã®ã¿èª¬æããŸããã¿ã¹ã¯éã§ã¢ãŒãã£ãã¡ã¯ããCIã«èªåã§è»¢éããåé¡ã解決ããå¿ èŠããããããçµ±åãã¹ãã䜿çšããæ°ãããã«ãã¯ãã¢ããªã±ãŒã·ã§ã³ãã«ãã®ã¿ã¹ã¯ããã¢ã»ã³ãã«ãããã¢ããªã±ãŒã·ã§ã³ã«ã¢ã¯ã»ã¹ã§ããããšãèŠããŠãããŠãã ããã
éçãªãµãŒããŒ
ã¢ããªã±ãŒã·ã§ã³ã§ãµãŒããŒãäžããã«ã¯ãng serveã®ä»£ãããå¿ èŠã§ããå€ãã®ãªãã·ã§ã³ããããŸãããæåã®-angular-http-serverããå§ããŸãããã®æ§æã«ã¯è€éãªãã®ã¯äœããããŸãããäŸåé¢ä¿ãã€ã³ã¹ããŒã«ããã¹ã¿ãã£ãã¯ãé 眮ãããŠãããã©ã«ããŒã瀺ããã¢ããªã±ãŒã·ã§ã³ãèµ·åããããŒãã瀺ããæºè¶³ããŠããŸãã
ãã®ãœãªã¥ãŒã·ã§ã³ã¯20åéå šäœã§ååã§ãããããã¹ãåè·¯ã«ããã€ãã®èŠæ±ããããã·ããå¿ èŠãããããšã«æ°ä»ããŸããã angular-http-serverã®ãããã·ã®æ¥ç¶ã«å€±æããŸãããæçµçãªè§£æ±ºçã¯ããµãŒããŒãExpressã«ã¢ããã°ã¬ãŒãããããšã§ããããã®åé¡ã解決ããããã«ãexpressããã³express-http-proxyèªäœã䜿çšãããŸãããç§ãã¡ã¯static.staticã䜿çšããŠéçå€æ°ãé åžããŸãã
ãã®çµæã次ã®ãããªã¹ã¯ãªãããåŸãããŸãã
const express = require('express');
const appStaticPathFolder = './dist';
const appBaseHref = './my/app';
const port = 4200;
const app = express();
app.use((req, res, next) => {
const accept = req
.accepts()
.join()
.replace('*/*', '');
if (accept.includes('text/html')) {
req.url = baseHref;
}
next();
});
app.use(appBaseHref, express.static(appStaticPathFolder));
app.listen(port);
ããã§èå³æ·±ãç¹ã¯ãã¢ããªã±ãŒã·ã§ã³ã®baseHrefã«ãŒãããªãã¹ã³ããåã«ããã¹ãŠã®ãªã¯ãšã¹ããåŠçããindex.htmlã®ãªã¯ãšã¹ããæ¢ãããšã§ããããã¯ããã¹ããã¢ããªã±ãŒã·ã§ã³ããŒãžã«ç§»åããå Žåã«è¡ãããŸãããã®ãã¹ã¯baseHrefãšã¯ç°ãªããŸãããã®ããªãã¯ãè¡ããªãå Žåãã¡ã€ã³ããŒãžä»¥å€ã®ã¢ããªã±ãŒã·ã§ã³ã®ããŒãžã«ç§»åãããšã404ãšã©ãŒã衚瀺ãããŸãã次ã«ããããã·ã®ãã³ããè¿œå ããŸãã
const proxy = require('express-http-proxy');
app.use(
'/common',
proxy('https://qa-stand.ru', {
proxyReqPathResolver: req => '/common' + req.url,
}),
);
äœãèµ·ãã£ãŠããã®ãã詳ããèŠãŠã¿ãŸããããå®æ°ããããŸãïŒ
- appStaticForlderPath-ã¢ããªã±ãŒã·ã§ã³ã®éçãé 眮ãããŠãããã©ã«ããŒã
- appBaseHref-ã¢ããªã±ãŒã·ã§ã³ã«baseHrefãããå ŽåããããŸãããªãå Žåã¯ãã/ããæå®ã§ããŸãã
/ commonã§å§ãŸããã¹ãŠã®ãªã¯ãšã¹ãããããã·ãããããã·ãããšãã¯ãproxyReqPathResolverèšå®ã䜿çšããŠããªã¯ãšã¹ããšåããã¹ãä¿åããŸãã䜿çšããªãå Žåããã¹ãŠã®ãªã¯ãšã¹ãã¯https://qa-stand.ruã«éä¿¡ãããŸãã
ã«ã¹ã¿ãã€ãºindex.html
ãµã€ãã¬ã¹ã¢ãŒãã§ã¢ããªã±ãŒã·ã§ã³ãæäŸãããšãã«äœ¿çšããã«ã¹ã¿ã index.htmlã®åé¡ã解決ããå¿ èŠããããŸãããnode.jsã§ç°¡åãªã¹ã¯ãªãããæžããŠã¿ãŸããããæåã®ãã©ã¡ãŒã¿ãŒãšããŠindex.modern.htmlãããããããindex.htmlã«å€æããããããäžèŠãªã¹ã¯ãªãããåé€ããå¿ èŠããããŸããã
const fs = require('fs');
const appStaticPathFolder = './dist';
fs.copyFileSync(appStaticPathFolder + '/index.modern.html', appStaticPathFolder + '/index.html');
fs.readFile(appStaticPathFolder + '/index.html', 'utf-8', (err, data) => {
const newValue = data
.replace(
'<script type="text/javascript" src="/auth.js"></script>',
'',
)
.replace(
'<script type="text/javascript" src="/analytics.js"></script>',
'',
);
fs.writeFileSync(appStaticPathFolder + '/index.html', newValue, 'utf-8');
});
ã¹ã¯ãªãã
ç§ã¯æ¬åœã«CIã§ãã¹ããå®è¡ããããã«ãã¹ãŠã®äŸåé¢ä¿ã®npm ciãå床å®è¡ããããªãã£ãã®ã§ïŒçµå±ãããã¯ã¢ããªã±ãŒã·ã§ã³ãã«ãã®ã¿ã¹ã¯ã§ãã§ã«è¡ãããŠããŸãïŒãç¬èªã®package.jsonã䜿çšããŠãããã®ãã¹ãŠã®ã¹ã¯ãªããçšã«å¥ã®ãã©ã«ããŒãäœæããããã«èŠããŸãããããšãã°ãintegration-tests-scriptsã®ããã«ãã©ã«ããŒã«ååãä»ããããã«3ã€ã®ãã¡ã€ã«ïŒserver.jsãcreate-index.jsãpackage.jsonïŒã眮ããŸããæåã®2ã€ã®ãã¡ã€ã«ã«ã€ããŠã¯äžã§èª¬æããŸããããpackage.jsonã®å 容ãåæããŸãããã
{
"name": "cypress-tests",
"version": "0.0.0",
"private": true,
"scripts": {
"create-index": "node ./create-index.js",
"main-app:serve": "node ./server.js",
"main-app:cy:run": "cypress run --project ./projects/main-app-integrations ",
"main-app:integrations": "npm run create-index && start-server-and-test main-app:serve http://localhost:4200/my/app/ main-app:cy:run"
},
"devDependencies": {
"@cypress/webpack-preprocessor": "4.1.0",
"@types/express": "4.17.2",
"@types/mocha": "5.2.7",
"@types/node": "8.9.5",
"cypress": "4.1.0",
"cypress-image-snapshot": "3.1.1",
"express": "4.17.1",
"express-http-proxy": "^1.6.0",
"start-server-and-test": "1.10.8",
"ts-loader": "6.2.1",
"typescript": "3.8.3",
"webpack": "4.41.6"
}
}
package.jsonã«ã¯ãçµ±åãã¹ãïŒtypescriptããã³ã¹ã¯ãªãŒã³ã·ã§ãããã¹ãããµããŒãïŒãå®è¡ããããã«å¿ èŠãªäŸåé¢ä¿ãšããµãŒããŒãèµ·åããAngular Workspaceã§ã®çµ±åãã¹ãã®å®è¡ã«é¢ããç« ã§ç¥ãããŠããindex.htmlããã³start-server-and-testãäœæããããã®ã¹ã¯ãªããã®ã¿ãå«ãŸããŠããŸã...
çºå£²
çµ±åãã¹ãã®å®è¡ãæ°ããDockerfileã«ã©ããããŸã-integration-tests-ci.DockerfileïŒ
FROM cypress/included:4.3.0
COPY integration-tests-scripts /app/
WORKDIR /app
RUN npm ci
COPY projects/main-app-integrations /app/projects/main-app-integrations
COPY dist /app/dist
COPY tsconfig.json /app/
ENTRYPOINT []
äžçªäžã®è¡ã¯åçŽã§ããintegration-tests-scriptsãã©ã«ããŒãã³ããŒããŠã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãã«å±éãããã¹ãã®å®è¡ã«å¿ èŠãªãã¹ãŠã®ãã®ãã³ããŒããŸãïŒãã®ã¹ã€ãŒãã¯ç°ãªãå ŽåããããŸãïŒãåã®ãã¡ã€ã«ãšã®äž»ãªéãã¯ãDockerã³ã³ãããŒå ã«ã¢ããªã±ãŒã·ã§ã³å šäœãã³ããŒããã®ã§ã¯ãªããCIã§ã®ãã¹ãå®è¡æéã®æå°éã®æé©åã ãã§ãã次ã®å 容ã§
ãã¡ã€ã«Integration-tests-ci.shãäœæããŸãã
docker build -t integrations -f integration-tests-ci.Dockerfile .
docker run --rm -v $PWD/projects/main-app-integrations/src:/app/projects/main-app-integrations/src integrations:latest npm run main-app:integrations
ãã¹ããå«ãã³ãã³ããå®è¡ãããšãintegration-tests-scriptsãã©ã«ããŒã®package.jsonãã«ãŒãã«ãªãããã®äžã§main-appïŒintegrationsã³ãã³ããå®è¡ãããŸãããããã£ãŠããã®ãã©ã«ããŒã¯ã«ãŒãã«å±éããããããã¢ããªã±ãŒã·ã§ã³ã®éçæ å ±ãå«ãŸããŠãããã©ã«ããŒãžã®ãã¹ã¯ããã¹ãŠãIntegration-tests-scriptsãã©ã«ããŒããã§ã¯ãªããã«ãŒãããèµ·åããããšããèãã§æå®ããå¿ èŠããããŸãã
ãŸããã¡ãã£ãšããçºèšãããããšæããŸããçµ±åãã¹ããå®è¡ããããã®æçµçãªbashã¹ã¯ãªãããããããç°ãªã圢ã§é²åãããšãã«åŒã³åºããŸããããããè¡ãå¿ èŠã¯ãããŸãããããã¯ããã®èšäºãèªãããã®äŸ¿å®ã®ããã ãã«è¡ãããŸãããããšãã°ããã§ã«éçºäžã®Integration-tests.shãªã©ãåžžã«1ã€ã®ãã¡ã€ã«ãæ®ããŠããå¿ èŠããããŸãããªããžããªã«è€æ°ã®ã¢ããªã±ãŒã·ã§ã³ãããããããã®æºåæ¹æ³ãç°ãªãå Žåã¯ãbashã§å€æ°ã䜿çšã§ããŸããããŸãã¯ã¢ããªã±ãŒã·ã§ã³ããšã«ç°ãªããã¡ã€ã«-å¿ èŠã«å¿ããŠã
æŠèŠ
å€ãã®æ å ±ããããŸãã-ç§ã¯ä»ãäžèšã«åºã¥ããŠèŠçŽãã䟡å€ããããšæããŸãã
ç°¡åãªã¹ã¯ãªãŒã³ã·ã§ãããã¹ãã䜿çšããŠãããŒã«ã«ã§ã®æžã蟌ã¿ãšãã¹ããå®è¡ããããã®ããŒã«ãæºåããŸãã
- ãµã€ãã¬ã¹ã«äŸåé¢ä¿ã眮ããŸãã
- ãã¹ãã§ãã©ã«ããŒãæºåããŸãã
- Angular Single Application-ãã¹ãŠãcypressãã©ã«ããŒã«æ®ããŸãã
- Angular Workspace-ãã¹ãã远跡ããã¢ããªã±ãŒã·ã§ã³ã®é£ã«çµ±åã¢ããªã±ãŒã·ã§ã³ã®ãã©ã«ããŒåãäœæãããã¹ãŠãcypressãã©ã«ããŒããããã«è»¢éããŸãã
- NX-ãããžã§ã¯ãã®ååãappname-e2eããappname-integrationsã«å€æŽããŸãã
- cypress- â build- Cypress, aot, index.html, environment prod- serve- Cypress ( , - prod-, ).
- :
- Angular Single Application â serve- cypress- , start-server-and-test.
- Angular Workspace â Angular Single Application, cypress run/open.
- NX â ng e2e.
- -:
- cypress-image-snapshot.
- CI.
- ãã¹ãã§ã¯ãã©ã³ãã ã«ã¹ã¯ãªãŒã³ã·ã§ãããæ®ãããšã¯ãããŸãããã¹ã¯ãªãŒã³ã·ã§ããã®åã«ã¢ãã¡ãŒã·ã§ã³ãããå Žåã¯ããããåŸ ã€ããã«ããŠãã ãããããšãã°ãã¢ãã¡ãŒã·ã§ã³èŠçŽ ã«Cypressã¢ãµãŒã·ã§ã³ãè¿œå ããŸãã
- æ¥ä»ã¯cy.clockã§æ¿¡ããŠããããã¹ã¯ãªãŒã³ã·ã§ãããæ®ããšãã«ãã©ãã¯ã¢ãŠããªãã·ã§ã³ã䜿çšããŠããŸãã
- ã«ã¹ã¿ã ã®cy.waitForResourceã³ãã³ãïŒç»åããã©ã³ããªã©ïŒã䜿çšããŠãå®è¡æã«ããŒãããããã¹ãŠã®éçèŠçŽ ãæåŸ ããŸãã
- ãã¹ãŠãDockerã§ã©ããããŸãã
- DockerfileãæºåããŠããŸãã
- bashãã¡ã€ã«ãäœæããŸãã
ã¢ã»ã³ãã«ãããã¢ããªã±ãŒã·ã§ã³ã®äžã§ãã¹ããå®è¡ããŸãã
- CIã§ã¯ããã«ãéã§ã¢ã»ã³ãã«ãããã¢ããªã±ãŒã·ã§ã³ã®ã¢ãŒãã£ãã¡ã¯ããã¹ããŒããæ¹æ³ãåŠã³ãŸãïŒããã¯ãŠãŒã¶ãŒã«æ®ããŸãïŒã
- integration-tests-scriptsãã©ã«ããŒã®æºåïŒ
- ã¢ããªã±ãŒã·ã§ã³ã®ãµãŒããŒãèµ·åããã¹ã¯ãªããã
- index.htmlãå€æŽããã¹ã¯ãªããïŒå ã®index.htmlã«æºè¶³ããŠããå Žåã¯ãã¹ãããã§ããŸãïŒã
- å¿ èŠãªã¹ã¯ãªãããšäŸåé¢ä¿ãå«ãpackage.jsonãã©ã«ããŒã«è¿œå ããŸãã
- æ°ããDockerfileãæºåããŠããŸãã
- bashãã¡ã€ã«ãäœæããŸãã
圹ç«ã€ãªã³ã¯
- Angular Workspace + Cypress + CI â Angular Workspace CI , ( typescript).
- Cypress â trade-offs.
- Start-server-and-test â , .
- Cypress-image-snapshot â -.
- Cypress recipes â Cypress, .
- Flaky Tests â , Google.
- Github Action â Cypress GitHub Action, README , â wait-on. docker.