【问题标题】:How to set up a selenium test of download a file in Gitlab CI如何在 Gitlab CI 中设置下载文件的硒测试
【发布时间】:2021-12-26 15:40:26
【问题描述】:

我正在编写一个硒测试来验证正在下载的文件。它在本地运行良好。而且我可以通过“目标”文件夹和容器 /home/seluser/Downloads 轻松访问该文件。

测试脚本是:

@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);
    } 
}

让我解释一下。首先,我在项目根存储库中创建一个名为“target”的文件夹。然后我通过 docker-compose 文件中的容器卷在 chrome docker 容器中设置下载路径。

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"

此设置在本地运行良好。当我在 gitlab CI 中运行它时,我无法将空折叠推送到 gitlab,因此我必须创建一个文件并将其存储在文件夹中并将其推送到 gitlab。但它是测试脚本,我在设置阶段删除了这个文件,以防它干扰断言。但是管道失败了。结果并没有给我更多的细节,只是说assertionException。这是 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

我想知道是否有人在 gitlab CI 中进行过这个下载测试。我认为我设置的下载路径可能不适用于 gitlab CI。我什至不知道如何检查文件是否已下载 gitlab CI.Thanks。

【问题讨论】:

  • @sytech 很抱歉打扰您。但是你对 docker 和 gitlabCI 有很好的了解。所以我想知道你对这个话题有什么建议。
  • 当然,我会尽快提供答案。这里的解决方案与您之前的问题具有相似的含义。绑定挂载的 docker 卷和相关文件将存在于容器/docker 守护进程上——而不是运行器主机上。
  • 我还可能会仔细检查您处理无法推送空目录的方法。也许只需将mkdir target 添加到工作脚本的开头即可。我不能 100% 确定您的 Java 代码正在创建目录。
  • 其实我收回我之前的评论——在使用docker:dind 和 docker-compose 时绑定挂载应该可以正常工作——我认为你不需要创建一个空文件并将其推送到亚搏体育app。这可能会使您的测试用例失败。如果docker compose up 不存在,则会在您执行docker compose up 时创建目录target。尝试从您的代码中删除该目录,看看是否有帮助。包含测试用例/断言的调试消息也会很有帮助。
  • @sytech 您好,感谢您的回复。我尝试删除项目存储库中的文件夹,并且没有更改测试脚本中的任何代码。当我在本地运行它时,它会在我的项目存储库中生成一个“目标”文件夹并成功运行。但是当我在gitlab CI中运行它时,它失败了,错误是'AssertionError'。

标签: docker selenium gitlab-ci selenium-grid downloadfile


【解决方案1】:

我不完全知道您希望在 http://docker:4444 上运行什么,但这似乎不正确:driver = new RemoteWebDriver(new URL("http://docker:4444/wd/hub"), cap);

我猜你想连接 selenium-hub。就个人而言,我总是更喜欢使用 GitLab 服务而不是在您的管道中运行 docker-compose。也许this answer 在 GitLab 中使用 Docker 运行 E2E 测试会有所帮助。

【讨论】:

  • 您好,感谢您的回复。我需要为每个浏览器容器设置卷以设置下载路径。如果我将 selenium/chrome 作为服务运行,那么我无法设置音量。 driver = new RemoteWebDriver(new URL("docker:4444/wd/hub"), cap); 用于正确的 selenium hub 和测试脚本。因为我使用了 "seleniumhub'sIPaddress:4444/wd/hub" 但它不起作用。我从这里得到了帮助。@987654324 @
  • 现在我的问题是当我想下载一个文件时,gitlab-ci 中的下载路径是什么?它似乎不适用于我在容器卷中设置的下载路径。
【解决方案2】:
  1. 声明:'让我解释一下。首先,我在项目根存储库中创建一个名为“target”的文件夹。' 我假设您正在通过执行 folder = new File("target"); 创建它,这实际上不会创建目录,您需要应用一些东西像下面这样:
String directory = "/target";
directory.mkdir()

但是,当您的这部分代码运行时,这实际上不会创建目录,因为您的 docker-compose.yml 将来自您的 chrome-node 的卷映射配置映射到主机 /目标目录。

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

这已经存在,因为 docker 会创建它,所以 java 代码将返回一个布尔值“false”(因为它不需要创建目录)并继续下一步。

  1. docker-compose.yml:您的“selenium/node-chrome”映像有一个映射,您已在其中映射/target /home/seluser/Downloads。由于在运行 'docker-compose up' 时该目录最初并不存在,因此 docker 将在主机上创建该目录,以便将其映射到您所需的卷。这里有 2 个问题,首先 docker 以 root 身份运行,并将在主机上创建新的 '/target' 目录,但只授予它 linux 权限' drwxr-xr-x' (755)。这意味着只有 root 用户可以写入该目录。所以即使配置已经映射了volume,当你以'seluser'的身份下载到目录时,它将无法写入,浏览器会返回一个'Permission denied' 响应。

  2. 另一个问题是java代码向RemoteWebDriver声明下载需要保存到prefs.put("download.default_directory", folder.getAbsolutePath());,它已被声明为“target”,这是一个问题,因为浏览器所在的 chrome-node 没有名为“/target”的目录,因此将无法 无论如何下载。这是您的'断言异常'

    的原因

建议为了效率和稳定性应该做到以下几点:

  • 在“docker-compose down & docker-compose up --build --force-recreate --no-deps -d”之前更新 gitlab-ci.yml命令
mkdir /target
chmod -R 777 /target

这将确保该目录可以由 node-chrome 容器上的 'seluser' 写入

  • 更新 docker-compose.yml

对于 Windows 主机 => GitLab CI Docker(WSL2) => Chrome-Node Docker

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

对于 Linux 主机 => GitLab CI Docker(Linux) => Chrome-Node Docker

volumes:
  /target:/home/seluser/Downloads

这将确保 Chrome 浏览器可以找到名为“/target”的目录,并且 java 测试可以看到写入主机“/target”的文件目录

另外你的 selenium-hub 配置需要更新,发布事件和订阅事件的端口还没有映射,更新如下:

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

【讨论】:

  • 您好,非常感谢您的建议。文件夹 = 新文件(“目标”);用于定义文件夹,因为我需要稍后使用 folder.listFiles() 进行断言。我之前手动创建了一个文件夹,但是我知道docker-compose文件可以创建'target'文件夹,我不再手动创建这个文件夹了。
  • 我已经尝试过你的建议。在 yml 文件中添加 mkdir /target 和 chmod -R 777 /target 。并且还在 docker-compose 文件中将卷更改为 ./target:/target 。但结果是一样的。出现 AssertionError。
  • OK - 让我们进行一些故障排除。您可以访问 chrome-node 容器,以便您以 seluser 身份运行,将 cd 到 /target 目录,然后添加文件touch test.txt。看看你是否有正确的权限开始,希望这会成功,然后你可以检查你是否可以在主机 /target dir 上看到文件
  • 有些奇怪。当我在本地运行新的 docker-compose 文件时,音量设置成功。我可以看到容器路径是卷绑定内的 /target 。但是测试失败了。在项目存储库的“目标”文件夹和容器的 /target 中找不到文件。相反,我在 home/seluser/Downloads 中找到了该文件。在我运行 docker-compose up 之前,我已经关闭了旧的包含。我没有在测试脚本中使用过这个路径。
  • 在另一台电脑上运行的 gitlab runner,在 gitlab-ci 中运行测试时如何访问 chrome 容器。我可以在 gitlab-ci.yml 中运行 touch /target test.txt 吗?但是我怎么知道我是否添加它?
猜你喜欢
  • 2021-09-28
  • 2018-05-12
  • 1970-01-01
  • 2019-11-13
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
  • 2022-06-24
  • 1970-01-01
相关资源
最近更新 更多