如何并行执行Rake任务

3
我需要在多个设备和模拟器上运行黄瓜测试。目前我使用了Jenkins中的多个作业并进行参数化,实现了同时进行测试的目的。但是,在未来有更多设备加入时,我不想在Jenkins中创建无数个作业,所以我并不认为这是最好的方法。
我尝试过使用rake任务,但我发现它是顺序执行而非并行执行。
以下是这两个rake任务:
def run_cucumber(profile)
  Cucumber::Rake::Task.new do |t|
    t.profile = profile
  end
  Rake::MultiTask[:cucumber].invoke
end

task 'Device1' do |t|
  run_cucumber('MotoZ2Play')
end
task 'Device2' do |t|
  run_cucumber('MotoG5Plus')
end

以下是我如何使用多任务启动并行rake的方法:

multitask 'build_parallel' => ['Device1', 'Device2']

这似乎仍然是按顺序而非并行执行。
我尝试使用以下代码实现并行测试 gem:
Parallel.map([:Device1,:Device2,:Device3,:Device4,:Device5]) {|task| Rake::Task[task].invoke }

但是这似乎在我的cucumber特性文件中执行随机场景,我们希望按照我们编写的顺序执行场景。

我如何实现并行rake任务?

更新:

通过使用Parallel.each代替Parallel.map解决了这个问题。


老实说,我有点迷茫了。“并行”和“按照我们编写的顺序”这两个目标无法同时实现,它们相互矛盾。 - Aleksei Matiushkin
我猜你误解了,我们所说的“按顺序”是指一组场景(测试用例)在所有设备上并行执行,而不是“按我们想要运行的顺序”。例如:我有测试用例A、B、C、D、E,每个测试用例都在两个机架X和Y中,我希望这些X和Y并行运行,依次执行A、B、C、D、E,而不是E、B、C、A、D。 - Emjey
1
这个问题有点误导,因为您已经知道如何并行运行rake任务。如果您可以从单个Ruby线程创建多个设备实例,则每个测试用例可以并行运行其每个设备的代码..如果这有意义,您不一定需要完全并行运行整个rake任务。 - max pleaner
@maxpleaner 这让我可以使用parallel.each([:Device1, :Device2])而不是parallel.map,从而根据需要在设备上生成实例。谢谢。已经搞定 :) - Emjey
在这里增加一些额外的想法。在Jenkins中,不确定到底哪个版本引入了它,但现在可以在节点上运行并行任务。这意味着您可以使用一个执行器在节点上运行多个线程。当然,您需要注意正在运行多少个任务,因为可能会超载执行器。另一个选项可能是让Jenkins作业在不同的从机上启动x个作业,比如在AWS中的EC2实例,每个实例都有其自己定义的配置。 - Dono
多台机器不是我的菜,因为管理层目前不批准支持所有机器的预算。在Jenkins中,您是否正在讨论创建新作业并保持其参数化? - Emjey
2个回答

1

有一个名为parallel_testshttps://github.com/grosser/parallel_tests的宝石,它允许您创建自定义rake任务并并行运行它们。 您还可以指定要使用的CPU数量。

所以这是我刚刚做的一些简单示例:

namespace :my_task do
  task :a => :environment do
    100.times {
      puts "A"
    }
  end

  task :b => :environment do
    100.times {
      puts "B"
    }
  end

  task :c => :environment do
    Rake::Task["my_task:a"].execute
    Rake::Task["my_task:b"].execute
  end
end


而输出结果则类似于:

和输出是smthg like:


B
B
B
B
A
A
B
B
B
B
B
B
B
B
B
B
A
A
A
A
A
A
...

希望这有所帮助。

祝好


谢谢!我会试一下的。这似乎是更合适的解决方案,而不需要再次依赖外部库。 - Emjey
是的,确切地说,它基本上用于加速测试套件,但作者留下了一些空间,以便在其他情况下使用,例如这种情况。它在我们的几个领域表现良好。 - zauzaj

1
最佳解决方案是使用drake gem,它是rake的一个分支,增加了并发支持。我不知道为什么multitask对你无效,但主要问题是你不能指定要运行Rakefile的并发量。使用drake,你可以通过-j选项指定。这类似于make的-j选项。
安装方法如下:
 gem install drake

假设您有一个像这样的 Rakefile:
task :a do
  sleep 5
  puts "a"
end

如果你运行drake -j2,它将以并发数2运行,因此在5秒后"a"和"b"都将同时打印。
但是如果你运行drake(或drake -j1),则在5秒后只会看到"a",然后再过5秒才会看到"b"。
Drake已不再维护,但它仍然非常好用。我已经使用它开发Phusion Passenger 8年了。

谢谢!我很快会尝试这个! - Emjey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接