如何使用rspec测试多线程TCPServer [英] How to test a multi-threaded TCPServer with rspec

查看:132
本文介绍了如何使用rspec测试多线程TCPServer的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个非常简单的日期服务器:

I've written a really simple date server:

require 'socket'

s = TCPServer.new 3939
  while (conn = s.accept)
    Thread.new(conn) do |c|
      c.print "Enter your name: "
      name = c.gets.chomp
      c.puts "Hi #{name}, the date is..."
      c.print `date`
      c.close
    end
  end

用户连接,生成了一个线程,他们输入了名称,并返回了日期.很简单.

A user connects, a thread is spawned, they enter their name, the date is returned. Simple.

我想知道如何在rspec中测试类似的东西.我已有的一些想法:1.)使用VCR记录服务器连接,并使用Timecop冻结并返回日期. 2.)在before块中连接到实际服务器.我不完全确定该怎么做,因为当我运行rspec时,我认为它实际上在运行服务器...或者发生某种情况,终端只是冻结并等待某些东西...示例测试代码:

I'm wondering about how I would go abouts testing something like this in rspec. Some ideas that I've had: 1.) Use VCR to record a server connection and Timecop to freeze and return a date. 2.) Connect to the actual server in a before block. I'm not entirely sure how to do this as when I run rspec, I think it actually runs the server...or something happens that the terminal just kind of freezes and waits for something... example test code:

before
  @server = TCPSever.new 3939
end

it "does something.."
  conn = @server.accept
  # etc
end

after
  @server.close
end

3.)断开连接. 4.)甚至不要尝试测试是否创建了线程,只需将名称请求和日期响应放入方法中并对其进行测试.

3.) Stub the connection. 4.) Don't even try to test that threads are created, and just put the name request and date response into a method and test this.

我查看了puma的测试,以了解它们如何测试线程: https://github.com/puma/puma/blob/master /test/test_puma_server.rb#L27

I looked at puma's tests to see how they test threads: https://github.com/puma/puma/blob/master/test/test_puma_server.rb#L27

我非常感谢您的帮助.这只是一个简单的练习,我想了解如何最好地为这种服务器实施一些测试.就像模拟用户连接并输入他们的名字一样. 预先谢谢你.

I'd really appreciate some help with this. It's just a simple exercise where I'd like to see how best to implement some tests for this kind of server. Like, simulating a user connecting and entering their name. Thank you in advance.

推荐答案

我会考虑将服务器组织为具有以下签名的类:

I would consider organizing the server as a class with this signature:

class DateServer
  # Initialize the server.  If port is 0, find
  # an unused port and use that.
  def initialize(port = 0)
  def start
  def stop
  def port    # return the bound port
end

您的测试然后设置并关闭服务器:

Your test then sets up and tears down the server:

before do
  @server = Server.new
  @server.start
end

after do
  @server.stop
end

由于该服务器没有副作用,因此您的测试将连接到该服务器,发送一些东西,并收回一些东西:

Since this server has no side-effects, your test will connect to it, send some stuff, and get some stuff back:

it "prints the date" do
  @socket = TCPSocket.new("localhost", @server.port)
  @socket.puts "Fred"
  @socket.close_write
  output = @socket.read
  expect(output).to match /Hi Fred/
end

要检查输出中是否包含日期,请使用正则表达式.这是一个未经测试且可能不正确的示例:

To check that the output contains the date, either use a regular expression. Here's an untested and probably incorrect example:

  expect(output).to match /\w+ \w+ +\d+ \d+:\d+:\d+ \w+ \d+/

或者使用例如timecop宝石,以便测试可以确定时间,然后检查日期是否完全匹配.

Or use, e.g., the timecop gem so that the test can force the time, and then check for an exact match on the date.

此服务器没有副作用,但是如果这样做,我会将副作用放在自己的对象中.假设当用户名为"Barney"时,服务器可以重新启动该框.与其让服务器直接执行此操作,不如让服务器调用重新引导程序"对象.在您的测试中,创建一个伪造的重启程序并将其提供给服务器:

This server has no side-effects, but if it did, I would put the side-effects in their own objects. Let's say that the server can reboot the box when the user's name is "Barney". Instead of having the server do that directly, let it call a "rebooter" object. In your test, create a fake rebooter and give that to the server:

before do
  @rebooter = double(Rebooter)
  @server = Server.new(rebooter: @rebooter)
  @server.start
end

然后:

"it should reboot when Barney connects" do
  @rebooter.should_receive(:reboot)
  @socket = TCPSocket.new("localhost", @server.port)
  @socket.puts "Barney"
  @socket.close_write
  output = @socket.read
end

这篇关于如何使用rspec测试多线程TCPServer的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆