OS 特定测试 ruby

OS specific tests with ruby

我有以下 Rakefile

require 'bundler/gem_tasks'
require 'rake/testtask'

Rake::TestTask.new do |task|
  task.libs << %w(test lib)
  task.pattern = 'test/**/*_test.rb'
end

task default: :test

测试用minitest定义:

require 'test_helper'
require 'certmanager'

class CertificateTest < Minitest::Test
  context 'settings' do
    should 'retrieve settings' do
      assert_equal 'test123', Certmanager::Settings.key_passphrase
    end
  end
end

现在还有一些 OS 特定代码,例如 Linux 上的 FileUtils.ln_s 和 Windows 上的 FileUtils.cp。此代码需要不同的测试。在这种情况下,例如assert_equal filepath, File.readlink(linkpath) (Linux) 与 assert File.exist?(filepath) (windows)

区分 OS 类型的最佳做法是什么? 我是否没有以 Linux 可以测试 windows 特定代码的方式编写测试,反之亦然? 是否可以在测试中区分 "inline"? 是否需要有两个不同的测试集并在 Rakefile 中决定需要执行哪个集? Rakefile 甚至有可能吗?

为了能够运行每次测试而不管当前OS,我写了一个模块TestHelper。该模块包含几个方法

  • 为测试假装一个windows或posix环境
  • 未在实际 OS 上实现(或以不同方式工作)的方法的设置存根 - 目前我只在 windows
  • 上找到这些方法
  • 检查实际的OS是否为windows(如果有必要知道的话)

在测试中,可以简单地使用 TestHelper.setup_windows_envTestHelper.setup_posix_env,只要它必须 OS 具体。

require 'rbconfig'
require 'fileutils'
module TestHelper
  extend self

  def setup_windows_env
    is_windows?
    RbConfig::CONFIG.stubs(:[]).with('host_os').returns('windows')
    ENV.stubs(:[]).with('OS').returns('Windows_NT')
  end

  def setup_stubs_for_windows_in_posix_env
    class << FileUtils
      def ln_s(src, dest, options = {})
        File.open(dest, 'w') { |file| file.write src }
        return 0
      end
    end

    class << File
      def readlink(file_name)
        return File.read(file_name)
      end
    end
  end

  def setup_posix_env
    setup_stubs_for_windows_in_posix_env if is_windows?
    RbConfig::CONFIG.stubs(:[]).with('host_os').returns('darwin')
    ENV.stubs(:[]).with('OS').returns('OSX')
  end

  def is_windows?
    @is_windows ||= ApplicationToTest::Util::OS.is_windows?
  end
end

完整性ApplicationToTest::Util::OS.is_windows?:

require 'rbconfig'
module ApplicationToTest
  module Util
    module OS
      def self.is_windows?
        begin
          env_os = ENV['OS']
        rescue NameError
          return false
        end
        if RbConfig::CONFIG['host_os'] =~ /^mingw2$|^mingw$|^mswin$|^windows$/
            true
        elsif env_os  == 'Windows_NT'
            true
        else
            false
        end
      end
    end
  end
end