postcon/behat-shell-extension

一个用于远程和本地执行shell命令的Behat扩展

安装量: 24 319

依赖者: 0

建议者: 0

安全性: 0

星标: 5

关注者: 6

分支: 3

开放问题: 1

类型:behator-extension

dev-master 2021-02-18 08:49 UTC

This package is auto-updated.

Last update: 2024-09-23 22:53:25 UTC


README

Behat扩展,用于在特性内执行shell命令。shell命令可以在使用ssh的远程服务器上运行,也可以在没有网络的本地运行。此外,可以将本地文件部署到远程服务器上的目录。

安装

使用composer

composer require postcon/behat-shell-extension dev-master

使用方法

# run.feature

Feature: Running commands
  In order to run useful integration tests
  As a tester
  I want to execute shell commands and check their output

  Scenario: Run command on the default shell/server and define expected output
    When I run "pwd"
    Then It should pass
    And I see
    """
    /tmp
    """

  Scenario: Run command on the default shell/server and define expected output in inline-style
    When I run "pwd"
    Then It should pass
    And I see "/tmp"

  Scenario: Run command on the shell/server "app"
    When I run "app/console --env=prod do:mi:mi" on "app"
    Then It should pass
# copy.feature

Feature: Copy file
  In order to prepare integration tests
  As a tester
  I want to copy files to directories (on remote servers)

  Scenario: Copy a file to /tmp directory on default server (or at the local filesystem)
    Given I copy file "test.txt" to "/tmp"
    And I run "cat /tmp/test.txt"
    Then it should pass
    And I see
    """
    content of test.txt
    """

  Scenario: Copy a file to /tmp directory on "app" server
    Given I copy file "test.txt" to "/tmp" on "app"
    And I run "cat /tmp/test.txt" on "app"
    Then it should pass
    And I see
    """
    content of test.txt
    """

配置

要使用BehatShellExtension,需要在behat.yml(或behat.yml.dist)中进行配置。您想调用命令的每个服务器或shell都必须指定。

本地shell

以下示例显示了本地shell的最小配置。

# behat.yml
extensions:
  ShellExtension:
    default:
      type: local

可以提供两个额外的配置参数:命令执行的base_dirtimeout(秒;如果命令未在超时时间内终止,则将其停止,Behat特性失败)。

# behat.yml
extensions:
  ShellExtension:
    default:
      type: local
      base_dir: /tmp
      timeout: 10

远程服务器/ssh

要通过ssh访问远程服务器,最小配置如下

# behat.yml
extensions:
  ShellExtension:
    ...
    app:
      type: remote
      ssh_hostname: user@shell.example.com

ssh_hostname指定ssh服务器名称和用户名。使用附加参数,可以配置ssh连接,并指定sshscp二进制文件。

# behat.yml
extensions:
  ShellExtension:
    ...
    app:
      type: remote
      base_dir: /tmp
      ssh_hostname: user@shell.example.com
      ssh_options: -i ~/.ssh/id_rsa
      ssh_command: /usr/bin/ssh
      scp_command: /usr/bin/scp
      timeout: 20

如果我们有这个特性示例

Scenario:
  Given I copy file "test.txt" to "/tmp" on "app"
  And I run "cat /tmp/test.txt" on "app"

则生成的命令如下

/usr/bin/scp -i ~/.ssh/id_rsa 'test.txt' 'user@shell.example.com:/tmp'
/usr/bin/ssh -i ~/.ssh/id_rsa user@shell.example.com 'cd /tmp ; cat /tmp/test.txt'

Docker

要在Docker容器中执行命令,以下最小配置是合适的

# behat.yml
extensions:
  ShellExtension:
    ...
    app:
      type: docker
      docker_containername: app

这里,我们假设有一个这样的Docker容器

docker run --name=app -d nginx

以下是一个更详细的配置

# behat.yml
extensions:
  ShellExtension:
    ...
    app:
      type: docker
      base_dir: /tmp
      docker_containername: app
      docker_command: /usr/local/bin/docker
      docker_options: -u user
      timeout: 20

这里,给出了docker执行程序的位置,以及如果需要的话,给出了options

如果我们有这个特性示例

Scenario:
  Given I copy file "test.txt" to "/tmp" on "app"
  And I run "cat /tmp/test.txt" on "app"

则生成的命令如下

/usr/local/bin/docker cp 'test.txt' app:'/tmp'
/usr/local/bin/docker exec -u user app /bin/bash -c 'cd /tmp ; cat /tmp/test.txt'

Docker-Compose

通过更改docker_command参数,可以使用docker-compose服务而不是Docker容器

# behat.yml
extensions:
  ShellExtension:
    app:
      type: docker
      base_dir: /tmp
      docker_containername: app
      docker_command: /usr/local/bin/docker-compose
      docker-options: -T
      timeout: 20

重要的是要指定docker-options: -T以“禁用伪终端分配”。

这里,我们假设有一个这样的Docker-compose配置

# docker-compose.yml
version: '2'
services:
  app:
    image: php:7.1-fpm

目前,无法将文件复制到正在运行的docker-compose服务中(即缺少命令docker-compose cp)。

内部实现

在shell上执行$command命令字符串,当类型为local时,会以以下方式调用

$process = new Process($command, $serverConfig['base_dir']);
$process->setTimeout($serverConfig['timeout']);
$process->run();

以这种方式执行远程执行的命令字符串$command

if ($serverConfig['base_dir']) {
    $command = sprintf('cd %s ; %s', $serverConfig['base_dir'], $command);
}
$command = sprintf(
    '%s %s %s %s',
    $serverConfig['ssh_command'],
    $serverConfig['ssh_options'],
    $serverConfig['ssh_hostname'],
    escapeshellarg($command)
);

// e.g. ssh -i ~/.ssh/id_rsa user@shell.example.com 'cd /var/www ; app/console --env=prod do:mi:mi'

$process = new Process($command);
$process->setTimeout($serverConfig['timeout']);
$process->run();

当使用docker时,以这种方式执行命令字符串$command

if ($serverConfig['base_dir']) {
    $command = sprintf('cd %s ; %s', $serverConfig['base_dir'], $command);
}

$command = sprintf(
    '%s exec %s /bin/bash -c %s',
    $serverConfig['docker_command'],
    $serverConfig['docker_containername'],
    escapeshellarg($command)
);

// e.g. docker exec container /bin/bash -c 'cd /var/www ; app/console --env=prod do:mi:mi'

$process = new Process($command);
$process->setTimeout($serverConfig['timeout']);
$process->run();

许可证

本包所有内容均受MIT许可证许可。