2017-10-09 10 views
-1

RSpec을 사용하여 생성 한 젬을 테스트하려고합니다. 보석의 목적은 대기열을 만드는 것입니다 ('토끼'사용). 여러 서버의 프로세스간에 통신하는 역할을합니다.다중 프로세스 라이브러리의 RSpec 테스트

그러나 RSpec 실행 환경에서 여러 테스트 프로세스를 생성하지 않고 프로세스를 안전하게 작성하는 방법에 대한 문서는 찾을 수 없습니다 (모두 예제 실패 및 성공 표시). 여기

내가 테스트를하고 싶었던 것입니다 :

  • 스폰 어린이 프로세스를 주요 RSpec에 공정
  • 에서 큐에
  • 푸시 메시지를 기다리는 아이들에 큐를 소모
  • 를 처리
  • 어린이들이 멈추고 각 어린이에게서받은 메시지의 수를 기다립니다.

이제는 자식이 하나의 메시지 만 사용하고 중지되는 간단한 경우를 구현했습니다.

module Queues 
    # Basic CR accepting only jobs of type cmd_line 
    class CR 
    attr_reader :nb_jobs 
    def initialize 
     # opening communication pipes 
     @rout, @wout = IO.pipe 
     @nb_jobs = nil # not yet available. 
    end 
    def main 
     @todo = JobPipe.instance 
     job = @todo.pop do |j| 
     # accept only CMD_LINE type of jobs. 
     j.type == Messages::Job::CMD_LINE 
     end 
     # run command 
     %x{#{job.cmd}} 
     @wout.puts "1" # saying that we did one job 
    end 
    def run 
     @pid = Process.fork 
     if @pid.nil? then 
     # we are in the child 
     self.main 
     @rout.close 
     @wout.close 
     exit 
     end 
    end 
    def wait 
     @nb_jobs = @rout.gets(nil).to_i 
     Process.wait(@pid) 
     @rout.close 
     @wout.close 
     @nb_jobs 
    end 
    end 

    @job = Messages::Job.new({:type => Messages::Job::CMD_LINE, :cmd => "sleep 1" }) 

    RSpec.describe JobPipe do 
    context "one Orchestrator and one CR" do 
     before(:each) do 
     indalo_queue_pre_configure 
     end 

     it "can send a job with Orchestrator and be received by CR" do 
     cr = CR.new 
     cr.run # execute the C.R. process 
     todo = JobPipe.instance 
     todo.push(@job) 
     nb_jobs = cr.wait 
     expect(nb_jobs).to eql(1) 
     end 
    end 

    context "one Orchestrator and severals CR" do 
     it 'can send one job per CR and get all back' do 
     crs = Array.new(rand(2..10)) { CR.new } 
     crs.each do |cr| 
      cr.run 
     end 
     todo = JobPipe.instance 
     crs.each do |_| 
      todo.push(@job) 
     end 
     nb_jobs = 0 
     crs.each do |cr| 
      nb_jobs += cr.wait 
     end 
     expect(nb_jobs).to eql(crs.length) 
     end 
    end 
    end 

end 

편집 : 여기

현재 내 코드 질문입니다 (죄송합니다 바로 그것을 참을 수 없어, 이것은 실수) :

가 제대로 RSpec에를 사용하는 방법이 있나요 다중 프로세스 환경?

나는 코드 리뷰를 찾고 있지 않으며, 내가하고 싶은 것에 대한 명확한 예를 보여주고 싶었다. 여기에서는 포크를 사용했지만 RSpec 부분을 포함하여 모든 프로세스를 복제하고 테스트 스위트에서 기대할 수없는 수많은 RSpec 출력을 얻었습니다.

메인 프로그램 만 RSpec 출력/통계 및 서브 프로세스가 그것과 상호 작용할 것이라고 기대합니다.

내가 제대로 볼 수있는 유일한 방법은 포크가 아니라 다른 방법으로 서브 프로세스를 호출하는 것입니다. 어쩌면 나는이 질문에 홀로 대답한다 ...

RSpec을 잘 모르는 나는 외부 코드를 쓰지 않고 RSpec 안에서 그것을 수행하는 방법을 알고 있는지 궁금했다. 하나의 테스트 예제에 링크 된 별도의 코드를 사용하는 것은 좋은 생각이 아닙니다.

다중 프로세스 테스트에서 RSpec에 대해 this plugin을 발견했습니다. 유일한 것은 모의 (mock) 개념에 대해 모른다는 것입니다. 그러나 아마도 그것에 대해 배워야 할 것입니다 ...

+0

그럼, 무엇이 당신의 질문입니까? – DiegoSalazar

+0

stackoverflow에 오신 것을 환영합니다! =) Stackoverflow는 질문과 답변에 관한 유일한 사이트입니다. 여기에 좋은 프로그램의 시작이있는 것 같지만, 당신이 묻고있는 것이 명확하지 않습니다. 질문을 게시 할 때 현재 명확하지 않은 질문이 있어야합니다. 사람들이 커뮤니티에 코드를 작성하도록 요청할 때이를 잘못 해석 할 수 있습니다. 이는 분명히 싫은 일입니다. 프로그램에 대한 피드백을 찾고 있다면 https://codereview.stackexchange.com/을 사용해보십시오. 다시 오신 것을 환영합니다! – 0112

+0

나는 더 명확 해 지길 바래서 내 질문을 편집했습니다. – ShamoX

답변

0

좋아, Process.fork 메서드의 & 블록 인수를 사용하는 대답을 발견했습니다. 이 경우 모든 프로세스를 실제로 복제하지 않고 다른 프로세스에서 코드 블록을 실행 한 다음 0을 반환합니다 (Ruby doc에서 설명한 것처럼).

이렇게하면 어린이가 모든 RSpec 환경을 가져 와서 테스트 상태를 여러 번 표시 할 수 없습니다.

추 신 : 테스트의 STDOUT/STDERR을 오염시키지 않으려면 자식 프로세스의 STDOUT/STDERR을 리디렉션하는 것을 잊지 않도록주의하십시오.

PS2 : @rout를 호출하면 부모 측에서 @wout을 닫는 것을 잊지 마십시오.자식에서 자식을 닫을지라도 부모가 열어서 EOF가 발생하지 않도록 (내가 제시 한 코드의 버그) 부모가 열어서 (nil) 가져옵니다.

PS3 : 어린이/부모가 말하고 걸리는 것을 막기 위해 파이프 대신 두 개의 파이프를 사용하십시오. 어린 시절 오류지만 다시 했어.

PS4 : 어린이의 좀비 상태를 막기 위해 exit 문구 (& 블록 끝)를 사용하고 나머지 하위 프로세스가 죽을 때까지 기다리지 않아도됩니다.

그 긴 게시물에 대해 유감이지만 나에게도 좋다 ^^