Модульные тесты Ruby: запускать код после каждого неудачного теста - PullRequest
5 голосов
/ 23 марта 2012

Есть ли какой-то чистый и элегантный способ выполнить мой код сразу после неудачного утверждения в модульных тестах ruby ​​в Test::Unit, до того как teardown будет выполнено?

Я делаю автоматическое тестирование графического интерфейса и хочу сделать снимок экрана сразу после того, как что-то не получилось.

Ответы [ 2 ]

9 голосов
/ 25 марта 2012

Если вы используете 1.9, не используйте Test :: Unit :: TestCase в качестве базового класса.Создайте его подкласс и переопределите #run_test для спасения, сделайте снимок экрана и выполните ререйз:

class MyAbstractTestCase < Test::Unit::TestCase
  def run_test( *args )
    super(*args)
  rescue
    snapshot()
    raise
  end
end

В качестве альтернативы, и я думаю, что это на самом деле самый краткий путь, вы можете использовать ловушку before_teardown:

class MyTestCase < Test::Unit::TestCase
  add_teardown_hook do |tc|
    screenshot() unless tc.passed?   
  end
end

Это не сработает на тесте 1.8 / юнит, но будет работать с минимальным тестом в 1.9.

3 голосов
/ 23 марта 2012

Ну, вы можете расширить Test::Unit::Assertions, чтобы делать то, что вам нравится, я не думаю, что есть встроенный способ сделать это.Возможно, что-то вроде этого (быстро и грязно):

require 'test/unit'

module Test::Unit::Assertions
  def safe_assert(test, msg=nil)
    passed = msg.nil? ? assert(test) : assert(test,msg)
  ensure
    puts 'take screenshot' unless passed
  end
end

class MyTest < Test::Unit::TestCase
  def setup
    puts 'setup'
  end

  def teardown
    puts 'teardown'
  end

  def test_something
    safe_assert true

    puts 'before failing assert'
    safe_assert false, "message"
    puts 'after failing assert'
  end
end

вывод:

Loaded suite unittest
Started
setup
before failing assert
take screenshot
teardown
F
Finished in 0.001094 seconds.

  1) Failure:
test_something(MyTest) [unittest.rb:5]:
message

1 tests, 2 assertions, 1 failures, 0 errors, 0 skips

Test run options: --seed 58428

РЕДАКТИРОВАТЬ: вы могли бы на самом деле передать аргументы assert более простым способом:

module Test::Unit::Assertions
  def safe_assert(*args)
    passed = assert(*args)
  ensure
    puts 'take screenshot' unless passed
  end 
end

также, вы можете обернуть стандартный assert в begin - ensure - end блок, если вам нужна эта функция нечасто:

class MyTest < Test::Unit::TestCase
  def test_something
    safe_assert true

    puts 'before failing assert'
    begin
      passed = assert false, "message"
    ensure
      puts 'take screenshot' unless passed
    end
    puts 'after failing assert'
  end
end 

или вы создаетеметод, который обеспечивает скриншот, как в следующем примере.Это на самом деле кажется мне самым чистым способом:

def screenshot_on_fail
  passed = yield
ensure
  puts 'take screenshot' unless passed
end

class MyTest < Test::Unit::TestCase
  def test_something_else
    screenshot_on_fail do
      assert true
    end

    screenshot_on_fail do
      assert false, 'message'
    end
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...