SlideShare a Scribd company logo
How to test code
with mruby
mruby testing in the wild
self.introduce
=>
{
name: “SHIBATA Hiroshi”,
nickname: “hsbt”,
title: “Chief engineer at GMO Pepabo, Inc.”,
commit_bits: [“ruby”, “rake”, “rubygems”, “rdoc”, “tdiary”,
“hiki”, “railsgirls”, “railsgirls-jp”, “jenkins”],
sites: [“ruby-lang.org”, “rubyci.com”, “railsgirls.com”,
“railsgirls.jp”],
}
Today’s target
• Web engineer(Rails programmer)
• Operation engineer
• QA/test engineer
• mruby committer
Test Everything
• Application
• xUnit, BDD testing tool, End-to-End testing tool
• Middleware
• (nothing)
• Server with IaaS
• Serverspec, Infrataster
mruby
What's mruby?
“mruby is the lightweight implementation of the Ruby language
complying to (part of) the ISO standard. Its syntax is Ruby 1.9
compatible.”
https://github.com/mruby/mruby#whats-mruby
Differences between mruby and CRuby
• The mruby runtime and libraries are embedded all into a single
binary.
• By default, mruby provides just a minimum set of standard
libraries such as String, Array, Hash, etc.
• Some of standard libraries in CRuby are NOT ones in mruby, for
example, IO, Regex, Socket, etc..
• mruby doesn't provide “require”, “sleep”, “p”, etc.
Advantages of mruby
• Single binary without pure ruby files.
• Embeddable into middlewares like below:
• apache/nginx
• groonga
• mysql
• Fun!!1 # most important thing
ngx_mruby
Introduction to ngx_mruby
“ngx_mruby is A Fast and Memory-Efficient Web Server Extension
Mechanism Using Scripting Language mruby for nginx.”
https://github.com/matsumoto-r/ngx_mruby#whats-ngx_mruby
location /proxy {
mruby_set_code $backend '
backends = [
"test1.example.com",
"test2.example.com",
"test3.example.com",
]
backends[rand(backends.length)]
';
}
location /hello {
mruby_content_handler /path/to/hello.rb cache;
}
In “nginx.conf”!!!
How to build ngx_mruby (and mruby)
I suggest to try it on OS X or Linux environment. You can change
embedded mgem via “build_config.rb” in ngx_mruby. repository.
$ git clone https://github.com/matsumoto-r/ngx_mruby
$ git clone https://github.com/nginx/nginx
$ cd ngx_mruby
$ git submodule init && git submodule update
comment-out mruby-redis and mruby-vedis
$ ./configure —with-ngx-src-root=../nginx
$ make build_mruby
$ make
$ cd ../nginx
$ ./objs/nginx -V
Run ruby code with ngx_mruby
• mruby_content_handler/mruby_content_handler_code
• mruby_set/mruby_set_code
• mruby_init/mruby_init_code
• mruby_init_worker/mruby_init_worker_code
Sample code of ngx_mruby
class ProductionCode
def initialize(r, c)
@r, @c = r, c
end
def allowed_ip_addresses
%w[
128.0.0.1
]
end
def allowed?
if (allowed_ip_addresses & [@c.remote_ip, @r.headers_in['X-Real-IP'], @r.headers_in['X-Forwarded-
For']].compact).size > 0
return true
end
(snip for memcached)
end
return false
end
ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
Sample configuration of nginx
location /path {
mruby_set $allowed ‘/etc/nginx/handler/production_code.rb' cache;
if ($allowed = 'true'){
proxy_pass http://upstream;
}
if ($allowed = 'false'){
return 403;
}
}
Usecase of ngx_mruby
• Calculation of digest hash for authentication.
• Data sharing with Rails application.
• To replace ugly complex nginx.conf with clean, simple, and
TESTABLE ruby code.
Middleware
as a Code
Advanced topic of ngx_mruby
• Development process
• Continuous Integration
• Test
• Deployment
We'll focus only
on testing only
Testing
code of mruby
What’s motivation
• We are using ngx_mruby in production.
• We should test every production code.
• Testing mruby is a cutting edge technical issue.
Sample code of ngx_mruby
class ProductionCode
def initialize(r, c)
@r, @c = r, c
end
def allowed_ip_addresses
%w[
128.0.0.1
]
end
def allowed?
if (allowed_ip_addresses & [@c.remote_ip, @r.headers_in['X-Real-IP'], @r.headers_in['X-Forwarded-
For']].compact).size > 0
return true
end
(snip for memcached)
end
return false
end
ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
Prototype concept
• Use CRuby(version independent: 2.0.0, 2.1, 2.2)
• Use test-unit
• Test “ruby code” without real world behavior.
Dummy class of ngx_mruby
class Nginx
class Request
attr_accessor :uri, :headers_in, :args, :method, :hostname
def initialize
@uri = nil
@headers_in = {}
@args = nil
@method = 'GET'
@hostname = nil
end
end
class Connection
attr_accessor :remote_ip
def initialize
@remote_ip = nil
end
end
Skeleton of test-case
require_relative '../lib/production/code/path/mruby.rb'
class MRubyTest < Test::Unit::TestCase
def setup
@r = Nginx::Request.new
@c = Nginx::Connection.new
end
def test_discard_access
assert !ProductionCode.new(@r, @c).allowed?
end
end
Permit specific requests with IP address
require_relative '../lib/production/code/path/mruby.rb'
class MRubyTest < Test::Unit::TestCase
def setup
@r = Nginx::Request.new
@c = Nginx::Connection.new
end
def test_ip_access
@c.remote_ip = '128.0.0.1'
@r.uri = '/secret/file/path'
assert ProductionCode.new(@r, @c).allowed?
end
end
Run test
% ruby test/production_code_test.rb
Loaded suite test/production_code_test
Started
.........
Finished in 0.031017 seconds.
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
--------------------
9 tests, 15 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
--------------------
290.16 tests/s, 483.61 assertions/s
We can test it!
Testing requirements
• Environment
• OS and Architecture
• Library
• Middleware
• Code
• Input
Our concerns on CRuby testing
• We can test “ruby code”. But it’s not fulfill testing requirements.
We need to test ngx_mruby behavior.
• We use a lot of mock/stub classes. It’s ruby’s dark-side.
• We need to make easy task runner.
Testing

code of mruby

using mruby
Use mruby directly instead of CRuby
mruby-mtest
class Test4MTest < MTest::Unit::TestCase
def test_assert
assert(true)
assert(true, 'true sample test')
end
end
MTest::Unit.new.run
MRuby::Build.new do |conf|
(snip)
conf.gem :github => 'matsumoto-r/mruby-uname'
# ngx_mruby extended class
conf.gem ‘../mrbgems/ngx_mruby_mrblib'
con.gem :github => ‘iij/mruby-mtest’
(snip)
end
build_config.rb test_4m_test.rb
Inline testing for mruby-mtest
class ProductionCode
(snip)
end
if Object.const_defined?(:MTest)
class Nginx
(snip)
end
class ProductionCode < MTest::Unit::TestCase
(snip)
end
MTest::Unit.new.run
else
ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
end
Build mruby for mruby testing
$ cd ngx_mruby/mruby
$ cp ../build_config.rb .
$ make
$ cp bin/mruby /path/to/test/bin
You need to get mruby binary before embed ngx_mruby.
Test runner for mruby-mtest
require 'rake'
desc 'Run mruby-mtest'
task :mtest do
target = "modules/path/to/production/code"
mruby_binary = File.expand_path("../#{target}/test_bin/mruby", __FILE__)
mruby_files = FileList["#{target}/**/*.rb"]
mruby_files.each do |f|
absolute_path = File.expand_path("../#{f}", __FILE__)
system "#{mruby_binary} #{absolute_path}"
end
end
Advantage of mruby testing
Rapid!
% rake mtest
# Running tests:
.........
Finished tests in 0.007924s, 1135.7900 tests/s, 1892.9833 assertions/s.
9 tests, 15 assertions, 0 failures, 0 errors, 0 skips
Advantage of mruby testing
Direct use of mruby binary
% ./modules/nginx_app_proxy/test_bin/mruby -v
mruby 1.1.0 (2014-11-19)
^C
Next challenge
• mruby binary can have different library from one in production.
• For continuous integration, we need to prepare cross-compile or
live compile environment.
• Replace nginx.conf with mruby code backed by test code.
[RDRC 2015] [search]
We are hiring!!1

More Related Content

PDF
Middleware as Code with mruby
PDF
Practical ngx_mruby
PDF
Middleware as Code with mruby
PDF
Large-scaled Deploy Over 100 Servers in 3 Minutes
PDF
How to Begin Developing Ruby Core
PDF
mruby で mackerel のプラグインを作るはなし
PDF
20141210 rakuten techtalk
PDF
The details of CI/CD environment for Ruby
Middleware as Code with mruby
Practical ngx_mruby
Middleware as Code with mruby
Large-scaled Deploy Over 100 Servers in 3 Minutes
How to Begin Developing Ruby Core
mruby で mackerel のプラグインを作るはなし
20141210 rakuten techtalk
The details of CI/CD environment for Ruby

What's hot (20)

PDF
The secret of programming language development and future
PDF
How to develop Jenkins plugin using to ruby and Jenkins.rb
PDF
Dependency Resolution with Standard Libraries
KEY
Leave end-to-end testing to Capybara
PDF
RubyGems 3 & 4
PDF
OSS Security the hard way
PDF
What's new in RubyGems3
PDF
The Future of Dependency Management for Ruby
PDF
20140419 oedo rubykaigi04
PDF
Gate of Agile Web Development
PDF
RubyGems 3 & 4
PDF
20140425 ruby conftaiwan2014
PDF
Gems on Ruby
PDF
20140626 red dotrubyconf2014
PDF
Advanced technic for OS upgrading in 3 minutes
PDF
20140918 ruby kaigi2014
PDF
How to distribute Ruby to the world
PDF
Gemification for Ruby 2.5/3.0
PDF
20140925 rails pacific
PDF
How to distribute Ruby to the world
The secret of programming language development and future
How to develop Jenkins plugin using to ruby and Jenkins.rb
Dependency Resolution with Standard Libraries
Leave end-to-end testing to Capybara
RubyGems 3 & 4
OSS Security the hard way
What's new in RubyGems3
The Future of Dependency Management for Ruby
20140419 oedo rubykaigi04
Gate of Agile Web Development
RubyGems 3 & 4
20140425 ruby conftaiwan2014
Gems on Ruby
20140626 red dotrubyconf2014
Advanced technic for OS upgrading in 3 minutes
20140918 ruby kaigi2014
How to distribute Ruby to the world
Gemification for Ruby 2.5/3.0
20140925 rails pacific
How to distribute Ruby to the world
Ad

Viewers also liked (15)

PPTX
スクラムにおけるQAメンバー(非開発者)の関わり方を模索してみた
PDF
継続的Webセキュリティテスト testing casual talks2
PDF
WebのQAを5年間運営してみた
PDF
High Performance tDiary
PDF
GitHub Enterprise with GMO Pepabo
PDF
How DSL works on Ruby
PDF
How to Begin to Develop Ruby Core
PDF
成長を加速する minne の技術基盤戦略
PPTX
【STAC2017】テスト自動化システム 成長記
PDF
Practical Testing of Ruby Core
PDF
The story of language development
PDF
概説 テスト分析
PDF
Usecase examples of Packer
PDF
事例 アジャイルと自動化 後半(ヤフオク!アプリでの自動テストの事例紹介) at Ques vol.7( #ques7 ) 11/20/2015
PDF
技術的負債との付き合い方
スクラムにおけるQAメンバー(非開発者)の関わり方を模索してみた
継続的Webセキュリティテスト testing casual talks2
WebのQAを5年間運営してみた
High Performance tDiary
GitHub Enterprise with GMO Pepabo
How DSL works on Ruby
How to Begin to Develop Ruby Core
成長を加速する minne の技術基盤戦略
【STAC2017】テスト自動化システム 成長記
Practical Testing of Ruby Core
The story of language development
概説 テスト分析
Usecase examples of Packer
事例 アジャイルと自動化 後半(ヤフオク!アプリでの自動テストの事例紹介) at Ques vol.7( #ques7 ) 11/20/2015
技術的負債との付き合い方
Ad

Similar to How to test code with mruby (20)

PDF
Lightweight APIs in mRuby
PDF
Lightweight APIs in mRuby (Михаил Бортник)
PDF
Why we use mruby with Perl5?
PDF
Rubinius and Ruby | A Love Story
PDF
How to control physical devices with mruby
KEY
Ruby On Rails Ecosystem
KEY
Refactoring.the.ruby.way
PDF
Merb Camp Keynote
KEY
Introduction to JRuby
PDF
Treat your servers like your Ruby App: Infrastructure as Code
PDF
Ruby confhighlights
PPTX
Ruby и TestComplete
PDF
RVM and Ruby Interpreters @ RSC Roma 03/2011
PDF
ruby-cocoa
PDF
ruby-cocoa
PPTX
Ruby и TestComplete
KEY
Crate - ruby based standalone executables
KEY
Ruby'izing iOS development
ODP
PDF
Bsu on rails_testing
Lightweight APIs in mRuby
Lightweight APIs in mRuby (Михаил Бортник)
Why we use mruby with Perl5?
Rubinius and Ruby | A Love Story
How to control physical devices with mruby
Ruby On Rails Ecosystem
Refactoring.the.ruby.way
Merb Camp Keynote
Introduction to JRuby
Treat your servers like your Ruby App: Infrastructure as Code
Ruby confhighlights
Ruby и TestComplete
RVM and Ruby Interpreters @ RSC Roma 03/2011
ruby-cocoa
ruby-cocoa
Ruby и TestComplete
Crate - ruby based standalone executables
Ruby'izing iOS development
Bsu on rails_testing

More from Hiroshi SHIBATA (19)

PDF
Introduction of Cybersecurity with Ruby at RedDotRubyConf 2024
PDF
Introduction of Cybersecurity with OSS at Code Europe 2024
PDF
Long journey of Ruby Standard library at RubyKaigi 2024
PDF
Long journey of Ruby standard library at RubyConf AU 2024
PDF
Deep dive into Ruby's require - RubyConf Taiwan 2023
PDF
How resolve Gem dependencies in your code?
PDF
How resolve Gem dependencies in your code?
PDF
Ruby コミッターと歩む Ruby を用いたプロダクト開発
PDF
Why ANDPAD commit Ruby and RubyKaigi?
PDF
RailsGirls から始める エンジニアリングはじめの一歩
PDF
How to develop the Standard Libraries of Ruby?
PDF
Roadmap for RubyGems 4 and Bundler 3
PDF
The Future of library dependency management of Ruby
PDF
Ruby Security the Hard Way
PDF
The Future of library dependency manageement of Ruby
PDF
The Future of Bundled Bundler
PDF
Productive Organization with Ruby
PDF
Gems on Ruby
PDF
Gemification for Ruby 2.5/3.0
Introduction of Cybersecurity with Ruby at RedDotRubyConf 2024
Introduction of Cybersecurity with OSS at Code Europe 2024
Long journey of Ruby Standard library at RubyKaigi 2024
Long journey of Ruby standard library at RubyConf AU 2024
Deep dive into Ruby's require - RubyConf Taiwan 2023
How resolve Gem dependencies in your code?
How resolve Gem dependencies in your code?
Ruby コミッターと歩む Ruby を用いたプロダクト開発
Why ANDPAD commit Ruby and RubyKaigi?
RailsGirls から始める エンジニアリングはじめの一歩
How to develop the Standard Libraries of Ruby?
Roadmap for RubyGems 4 and Bundler 3
The Future of library dependency management of Ruby
Ruby Security the Hard Way
The Future of library dependency manageement of Ruby
The Future of Bundled Bundler
Productive Organization with Ruby
Gems on Ruby
Gemification for Ruby 2.5/3.0

Recently uploaded (20)

PPTX
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
PPTX
Sustainable Sites - Green Building Construction
PPTX
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
PPTX
Foundation to blockchain - A guide to Blockchain Tech
PDF
Model Code of Practice - Construction Work - 21102022 .pdf
PPTX
UNIT 4 Total Quality Management .pptx
PPTX
MCN 401 KTU-2019-PPE KITS-MODULE 2.pptx
PDF
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
PPTX
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
PPTX
Lesson 3_Tessellation.pptx finite Mathematics
PPTX
Strings in CPP - Strings in C++ are sequences of characters used to store and...
PDF
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
PPTX
KTU 2019 -S7-MCN 401 MODULE 2-VINAY.pptx
PDF
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
DOCX
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
PDF
Digital Logic Computer Design lecture notes
PDF
PPT on Performance Review to get promotions
PPTX
Construction Project Organization Group 2.pptx
PDF
Arduino robotics embedded978-1-4302-3184-4.pdf
PPTX
UNIT-1 - COAL BASED THERMAL POWER PLANTS
Recipes for Real Time Voice AI WebRTC, SLMs and Open Source Software.pptx
Sustainable Sites - Green Building Construction
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
Foundation to blockchain - A guide to Blockchain Tech
Model Code of Practice - Construction Work - 21102022 .pdf
UNIT 4 Total Quality Management .pptx
MCN 401 KTU-2019-PPE KITS-MODULE 2.pptx
July 2025 - Top 10 Read Articles in International Journal of Software Enginee...
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
Lesson 3_Tessellation.pptx finite Mathematics
Strings in CPP - Strings in C++ are sequences of characters used to store and...
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
KTU 2019 -S7-MCN 401 MODULE 2-VINAY.pptx
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
ASol_English-Language-Literature-Set-1-27-02-2023-converted.docx
Digital Logic Computer Design lecture notes
PPT on Performance Review to get promotions
Construction Project Organization Group 2.pptx
Arduino robotics embedded978-1-4302-3184-4.pdf
UNIT-1 - COAL BASED THERMAL POWER PLANTS

How to test code with mruby

  • 1. How to test code with mruby mruby testing in the wild
  • 2. self.introduce => { name: “SHIBATA Hiroshi”, nickname: “hsbt”, title: “Chief engineer at GMO Pepabo, Inc.”, commit_bits: [“ruby”, “rake”, “rubygems”, “rdoc”, “tdiary”, “hiki”, “railsgirls”, “railsgirls-jp”, “jenkins”], sites: [“ruby-lang.org”, “rubyci.com”, “railsgirls.com”, “railsgirls.jp”], }
  • 3. Today’s target • Web engineer(Rails programmer) • Operation engineer • QA/test engineer • mruby committer
  • 4. Test Everything • Application • xUnit, BDD testing tool, End-to-End testing tool • Middleware • (nothing) • Server with IaaS • Serverspec, Infrataster
  • 6. What's mruby? “mruby is the lightweight implementation of the Ruby language complying to (part of) the ISO standard. Its syntax is Ruby 1.9 compatible.” https://github.com/mruby/mruby#whats-mruby
  • 7. Differences between mruby and CRuby • The mruby runtime and libraries are embedded all into a single binary. • By default, mruby provides just a minimum set of standard libraries such as String, Array, Hash, etc. • Some of standard libraries in CRuby are NOT ones in mruby, for example, IO, Regex, Socket, etc.. • mruby doesn't provide “require”, “sleep”, “p”, etc.
  • 8. Advantages of mruby • Single binary without pure ruby files. • Embeddable into middlewares like below: • apache/nginx • groonga • mysql • Fun!!1 # most important thing
  • 10. Introduction to ngx_mruby “ngx_mruby is A Fast and Memory-Efficient Web Server Extension Mechanism Using Scripting Language mruby for nginx.” https://github.com/matsumoto-r/ngx_mruby#whats-ngx_mruby location /proxy { mruby_set_code $backend ' backends = [ "test1.example.com", "test2.example.com", "test3.example.com", ] backends[rand(backends.length)] '; } location /hello { mruby_content_handler /path/to/hello.rb cache; } In “nginx.conf”!!!
  • 11. How to build ngx_mruby (and mruby) I suggest to try it on OS X or Linux environment. You can change embedded mgem via “build_config.rb” in ngx_mruby. repository. $ git clone https://github.com/matsumoto-r/ngx_mruby $ git clone https://github.com/nginx/nginx $ cd ngx_mruby $ git submodule init && git submodule update comment-out mruby-redis and mruby-vedis $ ./configure —with-ngx-src-root=../nginx $ make build_mruby $ make $ cd ../nginx $ ./objs/nginx -V
  • 12. Run ruby code with ngx_mruby • mruby_content_handler/mruby_content_handler_code • mruby_set/mruby_set_code • mruby_init/mruby_init_code • mruby_init_worker/mruby_init_worker_code
  • 13. Sample code of ngx_mruby class ProductionCode def initialize(r, c) @r, @c = r, c end def allowed_ip_addresses %w[ 128.0.0.1 ] end def allowed? if (allowed_ip_addresses & [@c.remote_ip, @r.headers_in['X-Real-IP'], @r.headers_in['X-Forwarded- For']].compact).size > 0 return true end (snip for memcached) end return false end ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
  • 14. Sample configuration of nginx location /path { mruby_set $allowed ‘/etc/nginx/handler/production_code.rb' cache; if ($allowed = 'true'){ proxy_pass http://upstream; } if ($allowed = 'false'){ return 403; } }
  • 15. Usecase of ngx_mruby • Calculation of digest hash for authentication. • Data sharing with Rails application. • To replace ugly complex nginx.conf with clean, simple, and TESTABLE ruby code.
  • 17. Advanced topic of ngx_mruby • Development process • Continuous Integration • Test • Deployment
  • 18. We'll focus only on testing only
  • 20. What’s motivation • We are using ngx_mruby in production. • We should test every production code. • Testing mruby is a cutting edge technical issue.
  • 21. Sample code of ngx_mruby class ProductionCode def initialize(r, c) @r, @c = r, c end def allowed_ip_addresses %w[ 128.0.0.1 ] end def allowed? if (allowed_ip_addresses & [@c.remote_ip, @r.headers_in['X-Real-IP'], @r.headers_in['X-Forwarded- For']].compact).size > 0 return true end (snip for memcached) end return false end ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed?
  • 22. Prototype concept • Use CRuby(version independent: 2.0.0, 2.1, 2.2) • Use test-unit • Test “ruby code” without real world behavior.
  • 23. Dummy class of ngx_mruby class Nginx class Request attr_accessor :uri, :headers_in, :args, :method, :hostname def initialize @uri = nil @headers_in = {} @args = nil @method = 'GET' @hostname = nil end end class Connection attr_accessor :remote_ip def initialize @remote_ip = nil end end
  • 24. Skeleton of test-case require_relative '../lib/production/code/path/mruby.rb' class MRubyTest < Test::Unit::TestCase def setup @r = Nginx::Request.new @c = Nginx::Connection.new end def test_discard_access assert !ProductionCode.new(@r, @c).allowed? end end
  • 25. Permit specific requests with IP address require_relative '../lib/production/code/path/mruby.rb' class MRubyTest < Test::Unit::TestCase def setup @r = Nginx::Request.new @c = Nginx::Connection.new end def test_ip_access @c.remote_ip = '128.0.0.1' @r.uri = '/secret/file/path' assert ProductionCode.new(@r, @c).allowed? end end
  • 26. Run test % ruby test/production_code_test.rb Loaded suite test/production_code_test Started ......... Finished in 0.031017 seconds. --------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- -------------------- 9 tests, 15 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 100% passed --------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------- -------------------- 290.16 tests/s, 483.61 assertions/s
  • 27. We can test it!
  • 28. Testing requirements • Environment • OS and Architecture • Library • Middleware • Code • Input
  • 29. Our concerns on CRuby testing • We can test “ruby code”. But it’s not fulfill testing requirements. We need to test ngx_mruby behavior. • We use a lot of mock/stub classes. It’s ruby’s dark-side. • We need to make easy task runner.
  • 31. Use mruby directly instead of CRuby mruby-mtest class Test4MTest < MTest::Unit::TestCase def test_assert assert(true) assert(true, 'true sample test') end end MTest::Unit.new.run MRuby::Build.new do |conf| (snip) conf.gem :github => 'matsumoto-r/mruby-uname' # ngx_mruby extended class conf.gem ‘../mrbgems/ngx_mruby_mrblib' con.gem :github => ‘iij/mruby-mtest’ (snip) end build_config.rb test_4m_test.rb
  • 32. Inline testing for mruby-mtest class ProductionCode (snip) end if Object.const_defined?(:MTest) class Nginx (snip) end class ProductionCode < MTest::Unit::TestCase (snip) end MTest::Unit.new.run else ProductionCode.new(Nginx::Request.new, Nginx::Connection.new).allowed? end
  • 33. Build mruby for mruby testing $ cd ngx_mruby/mruby $ cp ../build_config.rb . $ make $ cp bin/mruby /path/to/test/bin You need to get mruby binary before embed ngx_mruby.
  • 34. Test runner for mruby-mtest require 'rake' desc 'Run mruby-mtest' task :mtest do target = "modules/path/to/production/code" mruby_binary = File.expand_path("../#{target}/test_bin/mruby", __FILE__) mruby_files = FileList["#{target}/**/*.rb"] mruby_files.each do |f| absolute_path = File.expand_path("../#{f}", __FILE__) system "#{mruby_binary} #{absolute_path}" end end
  • 35. Advantage of mruby testing Rapid! % rake mtest # Running tests: ......... Finished tests in 0.007924s, 1135.7900 tests/s, 1892.9833 assertions/s. 9 tests, 15 assertions, 0 failures, 0 errors, 0 skips
  • 36. Advantage of mruby testing Direct use of mruby binary % ./modules/nginx_app_proxy/test_bin/mruby -v mruby 1.1.0 (2014-11-19) ^C
  • 37. Next challenge • mruby binary can have different library from one in production. • For continuous integration, we need to prepare cross-compile or live compile environment. • Replace nginx.conf with mruby code backed by test code.