1
votes

Les tests E2E angulaires ancrés réussissent sur la machine locale, mais expirent dans Travis CI

J'ai essayé d'ancrer mes tests angulaires e2e. Simplement, j'ai créé un fichier docker-compose.test.yml:

import { AppPage } from './app.po';

// Test bed
describe('workspace-project App', () => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage();
  });

  it('should display navbar with title',  () => {
    page.navigateTo().then(() => {
      console.log('Successfully connected to the page');
    });

    expect(page.getHeaderText()).toEqual('hobbies');

  });
});

Pour la configuration du rapporteur, j'ai suivi le tutoriel trouvé dans ce lien:

Tutoriel angulaire pour Travis CI

J'ai dû faire quelques ajustements en même temps:

 - Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
  - Failed: Timed out waiting for asynchronous Angular tasks to finish after 60 seconds. This may be because the current page is not an Angular application. Please see the FAQ for more details: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular

En utilisant la configuration, les tests e2e sont réussis sur ma machine locale. Cependant, lorsque j'exécute ceci dans le script pour .travis.yml:

before_script: 
    - docker-compose -f docker-compose.test.yml build
  script:
    - docker-compose -f docker-compose.test.yml run --name angular -p 4200:4200 angular

Travis CI échoue. Le résultat est:

let config = require('./protractor.conf').config;

// Tell protrator where the chrome driver is
// https://gitlab.com/dasch8/angular-ci/
// https://hub.docker.com/r/weboaks/node-karma-protractor-chrome/
config.chromeDriver = "/usr/bin/chromedriver";

config.allScriptsTimeout = 60000;

config.getPageTimeout = 60000;

config.jasmineNodeOpts.defaultTimeoutInterval = 60000;

// have it connect to the angular app
// config.baseUrl = "http://angular:4200";

config.capabilities = {
  browserName: 'chrome',
  chromeOptions: {
    args: ['--headless', '--no-sandbox', '--disable-gpu']
  },

};


exports.config = config;

C'est très étrange car j'ai écrit:

version: "3.4"

services:
  # set up angular app
  angular:
    build: 
      context: ./frontend
      dockerfile: sample.Dockerfile
      target: test
    image: angular:test
    container_name: angular
    ports: 
      - "4200:4200"
    depends_on: 
      - nodejs 
    command: npm run e2e -- --protractor-config=e2e/protractor-docker.conf.js --host 0.0.0.0

  nodejs:
    build:
      context: ./backend
      dockerfile: Dockerfile
      target: development
    image: nodejs:dev
    container_name: nodejs
    ports: 
      - "3000:3000"
    networks:
      - backend
    depends_on: 
      - db
    restart: always
  # the mongo database
  db:
    image: mongo
    container_name: db
    networks: 
      - backend
    ports: 
      - "27017:27017"
networks: 
  backend: 
    driver: bridge

Et dans les logs de Travis CI, le journal s'imprime:

Connexion réussie à la page. Le reste des journaux se trouve ici:

Mes journaux Travis CI

Je ne suis pas sûr de ce que je fais de mal. C'est tellement étrange que le test passe sur ma machine locale. J'ai essayé de résoudre cela d'une manière différente en utilisant des images sélénium / hub et sélénium / nœud-chrome et j'ai fait connecter le rapporteur à ce serveur sélénium. C'est la même histoire. Je l'ai fait fonctionner sur ma machine locale, mais cela échoue dans TravisCI. Je poserai des questions sur le problème du sélénium dans une autre question.


5 commentaires

Voulez-vous dire que les tests E2E dans le conteneur sont réussis sur votre machine, ou si vous les exécutez directement? Que se passe-t-il lorsque vous utilisez ces commandes docker-compose localement?


Les tests E2E dans le conteneur sont réussis sur ma machine. Lorsque j'ai exécuté les commandes docker-compose localement, les tests ont réussi. @jonrsharpe


Salut. J'ai augmenté toutes les valeurs de délai d'expiration (config.allScriptsTimeout, config.getPageTimeout, config.jasmineNodeOpts.defaultTimeoutInterval) à 180000 ms. Cela a fait passer mes tests sur Travis CI. Cependant, que se passe-t-il si je lance des tests qui prennent plus de temps? Dois-je deviner un délai d'attente approprié pour m'assurer que mes tests réussissent dans Travis CI?


Je suggérerais de préciser où exactement il échoue et d'ajouter une attente dynamique avant cela. Échoue-t-il systématiquement au même moment dans vos tests?


@ C.Peck Oui, il échoue toujours au même point. Je pensais aussi ajouter une attente.


3 Réponses :


0
votes

Alors, est-ce que l'ajout d'une attente comme suit affecte quelque chose?

import { AppPage } from './app.po';

// Test bed
describe('workspace-project App', () => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage();
  });

  it('should display navbar with title',  () => {
    page.navigateTo().then(() => {
      console.log('Successfully connected to the page');
    });

browser.ignoreSynchronization = true

driver.wait(function () {
return driver.isElementPresent(page.getHeaderText('hobbies'));
}, timeout);

    expect(page.getHeaderText()).toEqual('hobbies');

    browser.ignoreSynchronization = false;

  });
});


10 commentaires

J'ai fait ce que vous avez suggéré et j'ai toujours une erreur de temporisation. travis-ci.com/manofthelionarmy/ci_cd_project/jobs/182202345 Voici mon github repo pour le code que j'ai ajouté comme vous l'avez suggéré: github.com/manofthelionarmy/ci_cd_project/blob/... @ C.Peck


J'essaierais encore une chose: désactiver waitforAngular () avant l'action et lui dire de se rallumer après, notez les lignes browser.ignoreSychronization . Un résultat différent?


J'ai cloné votre projet mais j'ai beaucoup de configuration à faire pour le faire démarrer, mais je travaille dessus.


Je suggère de supprimer les lignes de cryptage dans mon .travis.yml. Travis s'arrêtera car j'ai chiffré certains fichiers en utilisant travis @ C.Peck


Je suis coincé avec l'erreur suivante en ce moment et je pense que tout est installé: Erreur: TSError: ⨯ Impossible de compiler TypeScript: erreur TS2688: Impossible de trouver le fichier de définition de type pour 'jasmine'. erreur TS2688: Impossible de trouver le fichier de définition de type pour «jasminewd2». erreur TS2688: Impossible de trouver le fichier de définition de type pour 'nœud'.


Cela donne l'impression que Jasmine n'est pas installé mais je le fais à 100%


Avez-vous exécuté npm install? La version angulaire que j'utilise est angulaire 7, donc je ne suis pas sûr si angular7 utilise des versions rétrogradées. J'ai trouvé ce lien: stackoverflow.com/a/46302864/10837566 . @ C.Peck


Ouais, j'ai trouvé ce même article et l'ai essayé mais ne fonctionne toujours pas.


Avez-vous essayé de courir sur un serveur autonome?


Non, je n'ai pas. J'ai posté ceci dans un commentaire ci-dessous: Je pense avoir trouvé le coupable possible. Dans environment.ts, il contient l'URL du backend NodeJs. Cependant, cette URL contient l'adresse IP de ma machine docker sur ma machine locale. Cette adresse IP n'est pas la même que celle de TravisCI. J'ai essayé de le remplacer par: http: // nodejs: 3000 car mon service nodejs de docker-compose est nommé nodejs



1
votes

J'ai suivi la réponse de C.Peck. J'ai testé sur ma machine locale et cela a fonctionné; cependant, cela ne fonctionnait toujours pas dans TravisCI, comme indiqué dans mes journaux:

Journaux TravisCI .

J'ai même défini le délai d'attente à 11 secondes, et les tests ont toujours échoué. J'ai ensuite augmenté le allScriptsTimeout dans protractor-docker.conf.js à 180000. Après cela, les tests ont réussi:

Mes journaux Travis CI du test Angular E2E réussi

Cependant, le test a duré 2 minutes et 10 secondes. C'est frustrant car je vérifiais simplement si le titre apparaît dans la barre de navigation. J'ai peur que si je teste quelque chose comme un formulaire et en cliquant sur des boutons, Travis CI peut même prendre plus de temps.


13 commentaires

Comme je le craignais, les tests expirent lorsque j'essayais de tester mon formulaire. Cela a fonctionné sur ma machine locale, mais expiration du délai sur Travis CI


Cela ne devrait pas être nécessaire, c'est un temps absurdement long à attendre constamment. J'aimerais pouvoir vous dire ce qui se passe, mais il y a clairement un problème ici.


Je ressens exactement la même chose et ces tests me font presque arracher les cheveux. @ C.Peck


Je pense avoir trouvé le coupable possible. Dans environment.ts, il contient l'URL du backend NodeJs. Cependant, cette URL contient l'adresse IP de ma machine docker sur ma machine locale. Cette adresse IP n'est pas la même que celle de TravisCI. J'ai essayé de le remplacer par: http: // nodejs: 3000 car mon service nodejs de docker-compose est nommé nodejs .


Si tel est le cas, je suis curieux de savoir pourquoi l'extension du délai d'expiration a permis aux tests de réussir?


Les tests ont réussi avant lorsque je vérifiais si un composant d'en-tête contenait le texte d'en-tête. J'ai ajouté de nouveaux tests qui impliquent de remplir un formulaire, et lors de la soumission, il fait une demande de demande de publication. Sur ngOnInit (), je le fais faire des demandes au serveur de nœuds, mais j'ai compris qu'il obtenait un ERR_CONNECTION_REFUSED dans Travis CI


Le problème auquel je suis maintenant confronté est que les noms DNS ne peuvent pas être résolus dans le navigateur. Ils ne peuvent être résolus que dans le conteneur docker du même réseau docker. Par conséquent, faire des requêtes http d'angular vers http: // localhost: 3000 et http: // nodjes: 3000 ne fonctionnera pas. Ce qui signifie que pour réussir, je dois obtenir l'adresse IP de l'hôte docker dans Travis CI, qui, j'ai peur, ne sera pas une adresse IP constante.


J'ai une idée de solution de contournement. J'ai une image de production pour mon application angulaire. Ses fichiers HTML statiques sont servis sur nginx. Le DNS du serveur nodejs est résolu lorsque j'utilise le proxy inverse de nginx. Par conséquent, je dois exécuter l'image de production, puis je dois exécuter le script de rapporteur séparément.


Ce qui peut également expliquer pourquoi mes tests stagnaient. Lorsque waitForAngularEnable (true), il attendra la fin des appels http. Puisque dans onNgOnit je fais des requêtes get, cela entraînera ERR_CONNECTION_REFUSED, rendant ainsi les tests stagnants.


@ C.Peck je l'ai résolu !!! Et je veux prendre le temps de vous dire merci d'avoir pris votre temps pour essayer de m'aider. Je vous en suis reconnaissant :)


Bon travail! Je déteste absolument ces problèmes que vous ne pouvez pas produire localement, heureux que vous ayez pu les résoudre.


Aussi, pourquoi ne pas mettre les détails de la solution dans votre réponse afin qu'elle puisse plus facilement aider toute autre personne susceptible de rencontrer ce problème


@ C.Peck Gotchu :)



1
votes

Enfin résolu !!! Alors, j'ai trouvé ce lien et je me suis inspiré: Chrome n'est pas accessible dans le réseau Docker

Heureusement, les configurations de l'individu étaient l'utilisation était presque la même, mais la partie intéressante était que l'individu effectuait un proxy inverse vers son application Web.

J'ai fait la même chose:

before_script: 
        - docker-compose -f docker-compose.selenium.yml build
script:
        - docker-compose -f docker-compose.selenium.yml up -d chrome_node proxy
        - docker container ls
        - docker-compose -f docker-compose.selenium.yml up protractor

Et pour mon application Web angulaire hébergée sur nginx:

let config = require('./protractor.conf').config;


// do not use the chromeDriver. If you do, it will not connect to Selenium service
config.directConnect = false;


// have it connect to the angular app
config.baseUrl = "http://proxy";

// Protractor getting the page-timeout
config.getPageTimeout = 60000;

// Selenium Webdriver timeout
config.allScriptsTimeout = 60000;

// Jasmine test script timeout
config.jasmineNodeOpts.defaultTimeoutInterval = 60000;

config.seleniumAddress = 'http://selenium-hub:4444/wd/hub'

config.capabilities = {
  browserName: 'chrome',
  chromeOptions: {
    args: ['--headless', '--disable-gpu', '--no-sandbox'],
  },
};

J'ai créé un conteneur distinct pour le rapporteur en utilisant mon image angulaire, que je fournirai:

version: '3.4'

services:
  selenium-hub:
    image: selenium/hub:3.141.59
    container_name: selenium-hub
    environment: 
      - GRID_TIMEOUT=10000
    ports: 
      - "4444:4444"
    privileged: true
    #tty: true

  chrome_node:
    image: selenium/node-chrome:3.141.59
    volumes: 
      - /dev/shm:/dev/shm
    container_name: chrome_node
    environment:
      - HUB_PORT_4444_TCP_ADDR=selenium-hub
      - HUB_PORT_4444_TCP_PORT=4444
    ports:
      - "5555:5555"
    privileged: true
    depends_on:
      - selenium-hub
    #tty: true
  proxy: 
    build: 
      context: ./proxy
      dockerfile: Dockerfile
    image: proxy
    container_name: proxy
    # HOST:CONTAINER
    ports: 
      - "80:80"
    #tty: true
    depends_on: 
      - angular
  angular:
    build:
      context: ./frontend
      dockerfile: sample.Dockerfile
      target: production
    image: angular:prod
    container_name: angular
    ports:
      - "4200:4200"
    privileged: true 
    depends_on: 
        - nodejs
    #tty: true
  nodejs:
    build:
      context: ./backend
      dockerfile: Dockerfile
      target: development
    image: nodejs:dev
    container_name: nodejs
    ports: 
      - "3000:3000"
    depends_on: 
      - db
    restart: always
    #tty: true
  # the mongo database
  db:
    image: mongo
    container_name: db
    ports: 
      - "27017:27017"
    #tty: true
  protractor:
    build:
      context: ./frontend
      dockerfile: sample.Dockerfile
      target: test
    image: angular:test
    container_name: protractor
    ports: 
      - "9876:9876"
    privileged: true
    depends_on:
      - selenium-hub
      - chrome_node
    #tty: true --> not neccesary
    command: npm run e2e -- --protractor-config=e2e/protractor-ci.conf.js --webdriver-update=false --dev-server-target= 


0 commentaires