简体   繁体   English

Ruby Watir:无法在Linux中的线程中启动浏览器

[英]Ruby Watir: cannot launch browser in a thread in Linux

I'm trying to run this code in Red Hat Linux, and it won't launch a browser. 我正在尝试在Red Hat Linux中运行此代码,并且它不会启动浏览器。 The only way I can get it to work is if i ALSO launch a browser OUTSIDE of the thread, which makes no sense to me. 我可以让它工作的唯一方法是,如果我也启动线程的浏览器OUTSIDE,这对我没有意义。 Here is what I mean: 这就是我的意思:

require 'watir-webdriver'
$alphabet = ["A", "B", "C"]
$alphabet.each do |z|
    puts "pshaw"
    Thread.new{
        Thread.current["testPuts"] =  "ohai " + z.to_s
        Thread.current["myBrowser"] = Watir::Browser.new :ff
        puts Thread.current["testPuts"]     }

    $browser = Watir::Browser.new :ff
end

the output is: 输出是:

pshaw
(launches browser)
ohai A
(launches browser)
pshaw
(launches browser)
ohai B
(launches browser)
pshaw
(launches browser)
ohai C
(launches browser)

However, if I remove the browser launch that is outside of the thread, as so: 但是,如果我删除了线程之外的浏览器启动,如下所示:

require 'watir-webdriver'
$alphabet = ["A", "B", "C"]

    $alphabet.each do |z|
puts "pshaw"
Thread.new{
    Thread.current["testPuts"] =  "ohai " + z.to_s
    Thread.current["myBrowser"] = Watir::Browser.new :ff
    puts Thread.current["testPuts"]     }
end

The output is: 输出是:

pshaw
pshaw
pshaw

What is going on here? 这里发生了什么? How do I fix this so that I can launch a browser inside a thread? 如何解决这个问题,以便我可以在线程中启动浏览器?

EDIT TO ADD: 编辑添加:

The solution Justin Ko provided worked on the psedocode above, but it's not helping with my actual code: 解决方案Justin Ko提供了上面的psedocode,但它并没有帮助我实际的代码:

require 'watir-webdriver'
require_relative 'Credentials'
require_relative 'ReportGenerator'
require_relative 'installPageLayouts'
require_relative 'PackageHandler'
Dir[(Dir.pwd.to_s + "/bmx*")].each {|file| require_relative file } #this includes all the files in the directory with names starting with bmx


module Runner
def self.runTestCases(orgType, *caseNumbers)
    $testCaseArray = Array.new

    caseNumbers.each do |thisCaseNum|
        $testCaseArray << thisCaseNum
    end

    $allTestCaseResults = Array.new
    $alphabet = ["A", "B", "C"]
    @count = 0
    @multiOrg = 0
    @peOrg = 0
    @eeOrg = 0
    @threads = Array.new
    $testCaseArray.each do |thisCase|
        $alphabet[@count] = Thread.new {    
            puts "working one"
            Thread.current["tBrowser"] = Watir::Browser.new :ff
            puts "working two"
            if ((thisCase.declareOrg().downcase == "multicurrency") || (thisCase.declareOrg().downcase == "mc"))
                currentOrg = $multicurrencyOrgArray[@multiOrg]
                @multiOrg += 1
            elsif ((thisCase.declareOrg().downcase == "enterprise") || (thisCase.declareOrg().downcase == "ee"))
                currentOrg = $eeOrgArray[@eeOrg]
                @eeOrg += 1         
            else #default to single currency PE
                currentOrg = $peOrgArray[@peOrg]
                @peOrg += 1
            end
            setupOrg(currentOrg, thisCase.testCaseID, currentOrg.layoutDirectory)
            runningTest = thisCase.actualTest()
            if runningTest.crashed != "crashed" #changed this to read the attr_reader isntead of the deleted caseStatus method from TestCase.rb
                cleanupOrg(thisCase.testCaseID, currentOrg.layoutDirectory)
            end
                        @threads << Thread.current
        }
        @count += 1     
    end 

    @threads.each do |thisThread|           
        thisThread.join
    end
    writeReport($allTestCaseResults)
end



def self.setupOrg(thisOrg, caseID, layoutPath)
    begin
        thisOrg.logIn
        pkg = PackageHandler.new
        basicInstalled = "false"
        counter = 0
        until ((basicInstalled == "true") || (counter == 5))
            pkg.basicInstaller()
            if Thread.current["tBrowser"].text.include? "You have attempted to access a page"
                thisOrg.logIn
            else    
                basicInstalled = "true"
            end
            counter +=1
        end
        if !((caseID.include? "bmxb") || (caseID.include? "BMXB"))
            moduleInstalled = "false"
            counter2 = 0
            until ((moduleInstalled == "true") || (counter == 5))
                pkg.packageInstaller(caseID)
                if Thread.current["tBrowser"].text.include? "You have attempted to access a page"
                    thisOrg.logIn
                else    
                    moduleInstalled = "true"
                end
                counter2 +=1
            end 
        end
        installPageLayouts(layoutPath)
    rescue
        $allTestCaseResults << TestCaseResult.new(caseID, caseID, 1, "SETUP FAILED!" + "<p>#{$!}</p><p>#{$@}</p>").hashEmUp
        writeReport($allTestCaseResults)
    end
end

def self.cleanupOrg(caseID, layoutPath)
    begin
        uninstallPageLayouts(layoutPath)
        pkg = PackageHandler.new
        pkg.packageUninstaller(caseID)
        Thread.current["tBrowser"].close
    rescue
        $allTestCaseResults << TestCaseResult.new(caseID, caseID, 1, "CLEANUP FAILED!" + "<p>#{$!}</p><p>#{$@}</p>").hashEmUp
        writeReport($allTestCaseResults)
    end
end



end

The output it's generating is: 它产生的输出是:

working one
working one
working one

It's not opening a browser or doing any of the subsequent code. 它不是打开浏览器或执行任何后续代码。

It looks like the code is having the problem mentioned in the Thread class documentation : 看起来代码遇到了Thread类文档中提到的问题:

If we don't call thr.join before the main thread terminates, then all other threads including thr will be killed. 如果我们在主线程终止之前没有调用thr.join,那么包括thr在内的所有其他线程都将被终止。

Basically your main thread is finishing pretty instantaneously. 基本上你的主要线程是瞬间完成。 However, the threads, which create browsers, take a lot longer than that. 但是,创建浏览器的线程需要更长的时间。 As result the threads get terminated before the browser opens. 结果,线程在浏览器打开之前终止。

By adding a long sleep at the end, you can see that your browsers can be opened by your code: 通过在最后添加长睡眠,您可以看到您的浏览器可以通过您的代码打开:

require 'watir-webdriver'
$chunkythread = ["A", "B", "C"]
$chunkythread.each do |z|
  puts "pshaw"
  Thread.new{
    Thread.current["testwords"] =  "ohai " + z.to_s
    Thread.current["myBrowser"] = Watir::Browser.new :ff
    puts Thread.current["testwords"]    }
end
sleep(300)

However, for more reliability, you should join all the threads at the end: 但是,为了获得更高的可靠性,您应该在最后加入所有线程:

require 'watir-webdriver'
threads = []
$chunkythread = ["A", "B", "C"]
$chunkythread.each do |z|
  puts "pshaw"
  threads << Thread.new{
    Thread.current["testwords"] =  "ohai " + z.to_s
    Thread.current["myBrowser"] = Watir::Browser.new :ff
    puts Thread.current["testwords"]    }
end
threads.each { |thr| thr.join }

For the actual code example, putting @threads << Thread.current will not work. 对于实际的代码示例,将@threads << Thread.current放入不起作用。 The join will be evaluating like @threads is empty. 连接将像@threads一样@threads为空。 You could try doing the following: 您可以尝试执行以下操作:

$testCaseArray.each do |thisCase|
    @threads << Thread.new {    
        puts "working one"
        Thread.current["tBrowser"] = Watir::Browser.new :ff

        # Do your other thread stuff
    }
    $alphabet[@count] = @threads.last
    @count += 1     
end 

@threads.each do |thisThread|           
    thisThread.join
end

Note that I am not sure why you want to store the threads in $alphabet . 请注意,我不确定为什么要将线程存储在$alphabet I put in the $alphabet[@count] = @threads.last , but could be removed if not in use. 我输入$alphabet[@count] = @threads.last ,但如果不使用则可以删除。

我卸载了Watir 5.0.0并安装了Watir 4.0.2,现在它工作正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM