Home > front end >  How to set up a selenium test of download a file in Gitlab CI
How to set up a selenium test of download a file in Gitlab CI

Time:11-17

I am writing a selenium test to verify a file being downloaded. It works fine in locally. And I can easily access the file both through the 'target' folder and inside the container /home/seluser/Downloads.

The test script is:

@BeforeMethod
public void setUp() throws  MalformedURLException {

    folder = new File("target");
    
    for(File file : folder.listFiles()) {
        file.delete();
    } 

    System.setProperty("webdriver.chrome.driver", "chromedriver.exe");
    ChromeOptions options = new ChromeOptions();

    Map<String, Object> prefs = new HashMap<String, Object>();
    prefs.put("profile.default_content_settings.popups", 0);
    prefs.put("download.default_directory", folder.getAbsolutePath());

    options.setExperimentalOption("prefs", prefs);
    DesiredCapabilities cap = new DesiredCapabilities();
    cap.setBrowserName("chrome");
    cap.setCapability(ChromeOptions.CAPABILITY, options);

    //driver = new ChromeDriver(cap);
    //driver = new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), cap);
    driver = new RemoteWebDriver(new URL("http://docker:4444/wd/hub"), cap);
}

@AfterMethod
public void tearDown() {
    driver.quit();
}

@Test
public void downloadFileTest() throws InterruptedException {
    driver.get("http://the-internet.herokuapp.com/download");
    driver.findElement(By.linkText("some-file.txt")).click();

    Thread.sleep(2000);
    File listOffFiles[] = folder.listFiles();
    Assert.assertTrue(listOffFiles.length > 0);

    for(File file : listOffFiles) {
        Assert.assertTrue(file.length() > 0);
    } 
}

Let me explain a little. First I create a folder named "target" in the project root repository. Then I set the download path in the chrome docker comtainer via container volumes in docker-compose file.

version: "3"
services:
  chrome:
    image: selenium/node-chrome:4.0.0-20211013
    container_name: chrome
    shm_size: 2gb
    depends_on:
      - selenium-hub
    volumes:
      - ./target:/home/seluser/Downloads
    environment:
      - SE_EVENT_BUS_HOST=selenium-hub
      - SE_EVENT_BUS_PUBLISH_PORT=4442
      - SE_EVENT_BUS_SUBSCRIBE_PORT=4443
      - SE_NODE_GRID_URL=http://localhost:4444
    ports:
      - "6900:5900"
  selenium-hub:
    image: selenium/hub:4.0.0-20211013
    container_name: selenium-hub
    ports:
      - "4444:4444"

This setting works fine locally. when I run it in the gitlab CI, i cannot push a empty fold to gitlab, so i have to create a file and store it in the folder and push it to gitlab. But it the test script, I delete this file in the setup stage in case it disturb the assertion. But the pipeline fails. The result does not give me more details , just said the assertionException. Here is the gitlab-ci.yml:

image: adoptopenjdk/openjdk11

stages:
  - gradle-build
  - docker-test

.gradle_template: &gradle_definition
  variables:
    GRADLE_OPTS: "-Dorg.gradle.daemon=false"
  before_script:
    - export GRADLE_USER_HOME=${CI_PROJECT_DIR}/.gradle

gradle-build:
  <<: *gradle_definition
  stage: gradle-build
  script:
    - chmod  x ./gradlew
    - ./gradlew --build-cache assemble
  cache:
    key: "$CI_COMMIT_REF_NAME"
    paths:
      - build
      - .gradle
  artifacts:
    paths:
      - build/libs/*.jar
    expire_in: 1 day
  only:
    - feature/multi-browsers

chrome-test:
  stage: docker-test
  image:
    name: docker/compose:1.29.2
    entrypoint: [ "/bin/sh", "-c" ]
  services:
    - docker:19.03.12-dind
  variables:
    DOCKER_TLS_CERTDIR: ""
    DOCKER_DRIVER: overlay2
    DOCKER_HOST: tcp://docker:2375/
  cache:
    key: "$CI_COMMIT_REF_NAME"
    policy: pull
    paths:
      - build
      - .gradle
  dependencies:
    - gradle-build
  before_script:
    - docker info
    - docker-compose --version
  script:
    - apk add --no-cache docker-compose
    - apk add openjdk11
    - docker-compose down
    - docker-compose up --build --force-recreate --no-deps -d
    - echo "Hello, chrome-test"
    - chmod  x ./gradlew
    - ./gradlew :test --tests "LogInTest_chrome"
  artifacts:
    when: always
    reports:
      junit: build/test-results/test/**/TEST-*.xml
    paths:
      - build/reports/*
    expire_in: 1 day
  only:
    - feature/multi-browsers

I wonder if someone has experience with this download test in gitlab CI. I think the download path I set maybe not work in gitlab CI. I even have no ideas how to check if a file is downloaded or not it gitlab CI.Thanks.

CodePudding user response:

I dont exactly know what you expect to run on http://docker:4444, but that seems not correct at: driver = new RemoteWebDriver(new URL("http://docker:4444/wd/hub"), cap);.

I geuss you want to connect with the selenium-hub instead. Personally I always prefer the use of GitLab services over running docker-compose in your pipeline. Maybe this answer about running E2E tests with Docker in GitLab helps.

CodePudding user response:

  1. Statement : 'Let me explain a little. First I create a folder named "target" in the project root repository.' I assume that you are creating this by executing folder = new File("target"); This actually will not create the directory, what you need to apply something like the following:
String directory = "/target";
directory.mkdir()

However, when this part of your code runs, this will not actually create the directory due to your docker-compose.yml where the volume mapping configuration from your chrome-node is mapped to the host /target directory.

volumes:
  ./target:/home/seluser/Downloads

This will already exist, as docker will create it, so the java code will return a boolean value of 'false' (as it does not need to create the directory) and will proceed to the next step.

  1. docker-compose.yml: there is a mapping for your 'selenium/node-chrome' image where you have mapped /target to /home/seluser/Downloads. As this directory does not initially exist when 'docker-compose up' is run, docker will create the directory on the host, so it can be mapped to your desired volume. Here lies 2 problems, first of all docker runs as root and will create the new '/target' directory on the host, but only gives it linux permissions 'drwxr-xr-x' (755). This means that only root user can write to that directory. So even though the configuration has mapped the volume, when you download to the directory as 'seluser', it will not be able to write and the browser will be returned with a 'Permission denied' response.

  2. The other issue is the java code declares to the RemoteWebDriver that the download will need to be saved to prefs.put("download.default_directory", folder.getAbsolutePath());, which has been declared as "target", this is an issue as the chrome-node where the browser resides does not have a directory called '/target', so will fail to download anyway. This is the cause of your 'assertion exception'

Propose that the following should be done for efficiency and stability:

  • Update the gitlab-ci.yml prior to the 'docker-compose down & docker-compose up --build --force-recreate --no-deps -d' commands
mkdir /target
chmod -R 777 /target

This will ensure that the directory can be written to by 'seluser' on the node-chrome container

  • Update the docker-compose.yml
volumes:
  ./target:/target

This will ensure that the Chrome browser can find a directory named '/target' and that the java test can see a file written to the host '/target' directory

Also your selenium-hub configuration needs to be updated, ports for publish events and subscribe events have not been mapped, update to the following:

  selenium-hub:
    image: selenium/hub:4.0.0-20211013
    container_name: selenium-hub
    ports:
      - "4442:4442"
      - "4443:4443"
      - "4444:4444"
  • Related