Bắt đầu với minitest

Minitest là một công cụ test tuyệt vời để kiểm tra các expectations của code. Nó cung cấp một cách đầy đủ các testing facilities supporting TDD, BDD, mocking và benchmarking. Cách minitest thực hiện khá đơn giản và dễ hiểu để bắt đầu.

Về cơ bản, nó được xây dựng từ các phần nhỏ và tập trung vào các step trong thiết kế. Khi mỗi step được hoàn thành, code sẽ được đánh giá và refactỏ để cung cấp 1 sự khác biệt giữa các vấn đề khác nhau. Điều này dẫn đến kết quả là Minitest trở nên dễ hiểu và dễ xây dựng, cho phép chúng ta bổ sung các test case rất dễ dàng.

Setting Up Minitest

Để chạy Minitest, config duy nhất chúng ta thực sự cần là yêu cầu các file autorun vào đầu của một test file:

require 'minitest/autorun'

Điều này rất tốt nếu bạn muốn giữ các đoạn code nhỏ gọn. Một cách tốt hơn để bắt đầu với Minitest là chúng ta sẽ tạo 1 project làm ví dụ:

bundle gem myproject

Và chúng ta sẽ có các file sau cho việc test:

Rakefile
test/test_helper.rb
test/myproject_test.rb

test_helper.rb là file mà chúng ta sẽ khởi tạo các configurations, plugins và các reporters. File này sẽ được included vào mỗi file test bởi dòng lệnh require 'test_helper'.

File myproject_test.rb là một file test ví dụ với một test case pass và 1 test case fail. Bất cứ file test nào bạn tạo ra đều cần có _test ở cuối tên file, ví dụ stuff_test.rb . Điều đó giúp cho Rakefile có thể đọc các file test của chúng ta. Hãy xem xét 1 đoạn test:


Rake::TestTask.new(:test) do |t|
  t.libs << "test"
  t.libs << "lib"
  t.test_files = FileList['test/**/*_test.rb']
end

task :default => :test

Ở đây chúng ta đã tạo ra 1 task :test, đó là nơi mà tất cả các file được định nghĩa để được chọn cho việc chạy test. Config dưới cùng cho phép chúng ta chỉ cần gõ rake để chạy các test.

Assert-Style Testing

Assert-style tests là 1 trong những dạng cơ bản nhất của test. Chúng là lựa chọn chính cho hầu hết các dự án Ruby online. Nhìn vào 1 file test generated từ Bundle, chúng ta có:


require 'test_helper'

class MyprojectTest < Minitest::Test
  def test_that_it_has_a_version_number
    refute_nil ::Myproject::VERSION
  end

  def test_it_does_something_useful
    assert false # this will result in a failure
  end
end

Về cơ bản, chúng ta sẽ có 1 lớp kế thừa Minitest::Test và định nghĩa tất cả các method sẽ chạy với test_. Trong mỗi case test, chung ta cần sử dụng assert hoặc refute cho mỗi đoạn code cần test.

Có một vài phương pháp khác nhau để lựa chọn. Chúng ta có thể thấy trong ví dụ, assertion được sử dụng thường xuyên nhất là assert_equal, trong đó có 2 giá trị để so sánh và thông báo lỗi tùy chọn.

Spec-Style Testing

Đây là phương án ưa thích của tôi. Nó dễ đọc hơn và gần với ngôn ngữ của chúng ta hơn:


require 'test_helper'

describe "My Project" do
  it "has a version number" do
    value(::Myproject::VERSION).wont_be_nil
  end

  it "does something useful" do
    value(4 + 4).must_equal 8
  end
end

Ngoài các assert, including setup/teardown, ở đây spec version còn có thêm :before:after. Đó là các methods bổ sung mà bạn có thể sử dụng để thực hiện các thao tác mình muốn trước khi chạy các dòng lệnh test (lazy named initializer)


let(:my_number) { 4 + 4 }

it "does something useful" do
  value( my_number ).must_equal 8
end

Với Minitest 5.6.0, các expectations (spec assertions) sẽ được di chuyển vào các giá trị monads (lưu ý là các cách viết cũ vẫn làm việc). Cho đến nay, tất cả các method spec-style đều được đưa trực tiếp vào các object class, có nghĩa là tất cả mọi thứ có method như must_equal hay wont_be_nil trong nó. Tuy nhiên tương lai điều đó sẽ được loại bỏ và ón sẽ được định nghĩa rõ ràng trong các giá trị monads. valueexpect sẽ là aliases của các method tương ứng với cách viết sử dụng _.

Dưới đây là 1 ví dụ:


# _(1 + 1).must_equal 2

# value(1 + 1).must_equal 2

# expect(1 + 1).must_equal 2

#

# This method of expectation-based testing is preferable to

# straight-expectation methods (on Object) because it stores its

# test context, bypassing our hacky use of thread-local variables

Benchmarking:

Để bắt đầu benchmarking code của bạn, hãy thêm đoạn mã sau vào rakefile:


Rake::TestTask.new(:bench) do |t|
  t.libs = %w(lib test)
  t.pattern = 'test/**/*_benchmark.rb'
end

Các file kết thúc bởi _benchmark trong project của chúng ta sẽ chạy khi execute rake bench. Một assert-style benchmarks cơ bản có thể thấy như sau:


require "test_helper"
require "minitest/benchmark" if ENV["BENCH"]

class MyprojectBenchmark < Minitest::Benchmark
  def bench_my_linear
    assert_performance_linear do |n|
      n.times do
        n*n
      end
    end
  end

  def bench_my_constant
    assert_performance_constant do |n|
      n*n
    end
  end
end

Mỗi tên method đều bắt đầu với bench_. Đối với spec style, bạn có thể thay thế các phương pháp tiền tố của assert_ với bench_ như thế này:


describe "My Project" do
  if ENV["BENCH"] then
    bench_performance_linear "my_linear" do |n|
      n.times do
        n*n
      end
    end
  end
end

Reporters:

Các reporter xử lí kết quả các bài test và đọc thông tin chi tiết cho chúng ta. Rõ ràng việc có 1 kết quả dễ đọc thực sự quan trọng trong việc cải thiện quá trình TDD. Để thêm các reporter vào config của riêng bạn, bạn sẽ cần cài đặt gem minitest-reporters trong Gemfile hoặc gemspec file. Bạn có thể kiểm tra các reporter bằng cách thêm vào cuối test_helper.rb:


require 'minitest/reporters'
Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new]

Đây chỉ là 1 trong nhiều style có sẵn cho các reporter. Các bạn có thể tìm hiểu thêm các reporter khác, ví dụ minitest-emoji hoặc color_pound_spec_reporter.


All Rights Reserved