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

What's hot (20)

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

Viewers also liked (15)

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

Similar to How to test code with mruby (20)

PPTX
Toolbox of a Ruby Team
Arto Artnik
 
PDF
Rails Performance
Wen-Tien Chang
 
PPTX
drupal ci cd concept cornel univercity.pptx
rukuntravel
 
PDF
Developing cross platform desktop application with Ruby
Anis Ahmad
 
KEY
Rails Presentation (Anton Dmitriyev)
True-Vision
 
PDF
Mojolicious lite
andrefsantos
 
PPT
Testing of javacript
Lei Kang
 
KEY
Cooking with Chef
Ken Robertson
 
PDF
Node azure
Emanuele DelBono
 
PDF
PHP QA Tools
rjsmelo
 
PDF
Practical Chef and Capistrano for Your Rails App
SmartLogic
 
PDF
Get your teeth into Plack
Workhorse Computing
 
PPTX
Azure from scratch part 4
Girish Kalamati
 
PDF
Profiling PHP with Xdebug / Webgrind
Sam Keen
 
PDF
introduction-infra-as-a-code using terraform
niyof97
 
PPTX
IronRuby - A brave new world for .Net (NDC2010)
Ben Hall
 
KEY
Jruby synergy-of-ruby-and-java
Keith Bennett
 
PPTX
АНДРІЙ ШУМАДА «To Cover Uncoverable» Online WDDay 2022 js
WDDay
 
PDF
[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey Gordeychik
CODE BLUE
 
PPTX
introduction to node.js
orkaplan
 
Toolbox of a Ruby Team
Arto Artnik
 
Rails Performance
Wen-Tien Chang
 
drupal ci cd concept cornel univercity.pptx
rukuntravel
 
Developing cross platform desktop application with Ruby
Anis Ahmad
 
Rails Presentation (Anton Dmitriyev)
True-Vision
 
Mojolicious lite
andrefsantos
 
Testing of javacript
Lei Kang
 
Cooking with Chef
Ken Robertson
 
Node azure
Emanuele DelBono
 
PHP QA Tools
rjsmelo
 
Practical Chef and Capistrano for Your Rails App
SmartLogic
 
Get your teeth into Plack
Workhorse Computing
 
Azure from scratch part 4
Girish Kalamati
 
Profiling PHP with Xdebug / Webgrind
Sam Keen
 
introduction-infra-as-a-code using terraform
niyof97
 
IronRuby - A brave new world for .Net (NDC2010)
Ben Hall
 
Jruby synergy-of-ruby-and-java
Keith Bennett
 
АНДРІЙ ШУМАДА «To Cover Uncoverable» Online WDDay 2022 js
WDDay
 
[CB20] Vulnerabilities of Machine Learning Infrastructure by Sergey Gordeychik
CODE BLUE
 
introduction to node.js
orkaplan
 
Ad

More from Hiroshi SHIBATA (19)

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

Recently uploaded (20)

PDF
Introduction to Ship Engine Room Systems.pdf
Mahmoud Moghtaderi
 
PDF
Packaging Tips for Stainless Steel Tubes and Pipes
heavymetalsandtubes
 
PDF
20ME702-Mechatronics-UNIT-1,UNIT-2,UNIT-3,UNIT-4,UNIT-5, 2025-2026
Mohanumar S
 
PPTX
Chapter_Seven_Construction_Reliability_Elective_III_Msc CM
SubashKumarBhattarai
 
PPTX
sunil mishra pptmmmmmmmmmmmmmmmmmmmmmmmmm
singhamit111
 
PDF
settlement FOR FOUNDATION ENGINEERS.pdf
Endalkazene
 
PDF
Biodegradable Plastics: Innovations and Market Potential (www.kiu.ac.ug)
publication11
 
PPTX
MT Chapter 1.pptx- Magnetic particle testing
ABCAnyBodyCanRelax
 
PDF
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
PPTX
ETP Presentation(1000m3 Small ETP For Power Plant and industry
MD Azharul Islam
 
PDF
Machine Learning All topics Covers In This Single Slides
AmritTiwari19
 
PDF
Air -Powered Car PPT by ER. SHRESTH SUDHIR KOKNE.pdf
SHRESTHKOKNE
 
PPTX
business incubation centre aaaaaaaaaaaaaa
hodeeesite4
 
PPTX
Ground improvement techniques-DEWATERING
DivakarSai4
 
PDF
Zero Carbon Building Performance standard
BassemOsman1
 
PDF
Advanced LangChain & RAG: Building a Financial AI Assistant with Real-Time Data
Soufiane Sejjari
 
PDF
勉強会資料_An Image is Worth More Than 16x16 Patches
NABLAS株式会社
 
PDF
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
PDF
AI-Driven IoT-Enabled UAV Inspection Framework for Predictive Maintenance and...
ijcncjournal019
 
PPTX
Inventory management chapter in automation and robotics.
atisht0104
 
Introduction to Ship Engine Room Systems.pdf
Mahmoud Moghtaderi
 
Packaging Tips for Stainless Steel Tubes and Pipes
heavymetalsandtubes
 
20ME702-Mechatronics-UNIT-1,UNIT-2,UNIT-3,UNIT-4,UNIT-5, 2025-2026
Mohanumar S
 
Chapter_Seven_Construction_Reliability_Elective_III_Msc CM
SubashKumarBhattarai
 
sunil mishra pptmmmmmmmmmmmmmmmmmmmmmmmmm
singhamit111
 
settlement FOR FOUNDATION ENGINEERS.pdf
Endalkazene
 
Biodegradable Plastics: Innovations and Market Potential (www.kiu.ac.ug)
publication11
 
MT Chapter 1.pptx- Magnetic particle testing
ABCAnyBodyCanRelax
 
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
ETP Presentation(1000m3 Small ETP For Power Plant and industry
MD Azharul Islam
 
Machine Learning All topics Covers In This Single Slides
AmritTiwari19
 
Air -Powered Car PPT by ER. SHRESTH SUDHIR KOKNE.pdf
SHRESTHKOKNE
 
business incubation centre aaaaaaaaaaaaaa
hodeeesite4
 
Ground improvement techniques-DEWATERING
DivakarSai4
 
Zero Carbon Building Performance standard
BassemOsman1
 
Advanced LangChain & RAG: Building a Financial AI Assistant with Real-Time Data
Soufiane Sejjari
 
勉強会資料_An Image is Worth More Than 16x16 Patches
NABLAS株式会社
 
67243-Cooling and Heating & Calculation.pdf
DHAKA POLYTECHNIC
 
AI-Driven IoT-Enabled UAV Inspection Framework for Predictive Maintenance and...
ijcncjournal019
 
Inventory management chapter in automation and robotics.
atisht0104
 

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.