<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>spacewander (罗泽轩)</title>
    <link>https://ruby-china.org/spacewander</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>Ruby China 要有小弟妹啦</title>
      <description>&lt;p&gt;&lt;a href="https://github.com/huacnlee/mediom" rel="nofollow" target="_blank"&gt;https://github.com/huacnlee/mediom&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="/huacnlee" class="user-mention" title="@huacnlee"&gt;&lt;i&gt;@&lt;/i&gt;huacnlee&lt;/a&gt; 的秘密计划&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/29cb11d705e73540a3178823a4b5c1ce.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>spacewander</author>
      <pubDate>Sun, 29 Mar 2015 21:21:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/24895</link>
      <guid>https://ruby-china.org/topics/24895</guid>
    </item>
    <item>
      <title>Rails 的 Cookie 问题现在怎么样了</title>
      <description>&lt;p&gt;今天发掘出了几篇旧闻。&lt;/p&gt;

&lt;p&gt;Nearly 2000 Sites Vulnerable to Ruby on Rails Cookie Problem:
&lt;a href="https://threatpost.com/ruby-on-rails-cookiestore-vulnerability-plagues-prominent-websites/103038" rel="nofollow" target="_blank"&gt;https://threatpost.com/ruby-on-rails-cookiestore-vulnerability-plagues-prominent-websites/103038&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;How bad is rails' cookie system?
&lt;a href="http://pothibo.com/2013/10/how-bad-is-rails-cookie-system" rel="nofollow" target="_blank"&gt;http://pothibo.com/2013/10/how-bad-is-rails-cookie-system&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Logout is broken by default in Ruby on Rails Web applications
&lt;a href="https://news.ycombinator.com/item?id=6545923" rel="nofollow" target="_blank"&gt;https://news.ycombinator.com/item?id=6545923&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;大体上是，Rails 的 Cookie 实现机制没有办法真正地清除掉客户端的 Cookie。&lt;/p&gt;

&lt;p&gt;如果不是先看到了日期，我肯定会被吓呆了。还好这是一两年前的事情，那时候我还没使用过 Rails 呢。
不知道 Rails 的 Cookie 实现现在怎么样了？&lt;/p&gt;</description>
      <author>spacewander</author>
      <pubDate>Tue, 10 Mar 2015 23:33:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/24579</link>
      <guid>https://ruby-china.org/topics/24579</guid>
    </item>
    <item>
      <title>There Is More Than One Way To Do It, Ruby 风格问题</title>
      <description>&lt;p&gt;开一个帖子解决我长期的疑惑：&lt;/p&gt;

&lt;p&gt;你&lt;/p&gt;

&lt;p&gt;1.
是喜欢用&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if !condition
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;还是用&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unless condition
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;2.
是喜欢用&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;do_something()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;还是用&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;do_something
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;3.
是喜欢用&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  return xxx
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;还是用&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  xxx
end
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;

&lt;p&gt;喜欢甜的还是咸的都没关系，只要你能说出你的理由。（当然你也可以根据本日运程选择使用哪种风格，只要理由说得通 &lt;img title=":sweat_smile:" alt="😅" src="https://twemoji.ruby-china.com/2/svg/1f605.svg" class="twemoji"&gt;）&lt;/p&gt;</description>
      <author>spacewander</author>
      <pubDate>Thu, 18 Dec 2014 23:38:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/23274</link>
      <guid>https://ruby-china.org/topics/23274</guid>
    </item>
    <item>
      <title>MiniTest 的正确使用姿势</title>
      <description>&lt;p&gt;MiniTest 是什么？不懂的请搜索一下，我就不解释了。&lt;/p&gt;

&lt;p&gt;在 MiniTest 之前，用 Ruby 做测试的有两种人，一种人喜欢 Test::Unit 的&lt;code&gt;test_*&lt;/code&gt;风格，另一种人喜欢 Rspec 的&lt;code&gt;describe&lt;/code&gt;风格。他们时不时因为这两种风格的优缺点以及哪一方才能代表真正的 Ruby 测试风格而争执不下。（这有点像《格列佛游记》中，两个小人国因从哪个方向打碎蛋壳而反目成仇）&lt;/p&gt;

&lt;p&gt;后来，MiniTest 出现了，改变了这一切。MiniTest 向众人宣讲道，“汝可择 Test::Unit 之道而从之，亦可择 Rspec 而从之”。在 MiniTest 里，你可以像 Test::Unit 那样写测试，也可以像 Rspec 那样写测试。是故，MiniTest 用一种包容的心态解决了纷争，重新给世界带来了和平。&lt;/p&gt;

&lt;p&gt;这篇文章，就是讲讲 MiniTest 的正确使用姿势。&lt;/p&gt;
&lt;h2 id="Hello World"&gt;Hello World&lt;/h2&gt;
&lt;p&gt;使用了 MiniTest 的测试代码像这样：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'minitest/autorun'&lt;/span&gt;

&lt;span class="c1"&gt;# 注意有些资料中，测试类不是继承自MiniTest::Test，&lt;/span&gt;
&lt;span class="c1"&gt;# 那是MiniTest 5之前的做法，MiniTest会通知你改正&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestMyLife&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MiniTest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Test&lt;/span&gt;
  &lt;span class="c1"&gt;# 这个方法会在各个测试之前被调用&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;
    &lt;span class="vi"&gt;@me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;People&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_sleep&lt;/span&gt;
     &lt;span class="c1"&gt;# assert_equal exp, act, msg&lt;/span&gt;
     &lt;span class="n"&gt;assert_equal&lt;/span&gt;   &lt;span class="s2"&gt;"zzZ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@me.sleep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"I don't sleep well "&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;teardown&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MiniTest 中可用的断言 (assert_*) 有很多个，具体可以看看文档：
&lt;a href="http://docs.seattlerb.org/minitest/Minitest/Assertions.html" rel="nofollow" target="_blank"&gt;http://docs.seattlerb.org/minitest/Minitest/Assertions.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;另外，在每个 test 方法之外，还可以执行被称为&lt;code&gt;lifeCycleHook&lt;/code&gt;的方法，比如前面的&lt;code&gt;setup&lt;/code&gt;和&lt;code&gt;teardown&lt;/code&gt;。
具体的顺序为：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;before_setup&lt;/li&gt;
&lt;li&gt;setup&lt;/li&gt;
&lt;li&gt;after_setup&lt;/li&gt;
&lt;li&gt;test&lt;/li&gt;
&lt;li&gt;before_teardown&lt;/li&gt;
&lt;li&gt;teardown&lt;/li&gt;
&lt;li&gt;after_teardown&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;看到这里你多半会觉得，有&lt;code&gt;setup&lt;/code&gt;和&lt;code&gt;teardown&lt;/code&gt;就够了，一大堆别的&lt;code&gt;before/after&lt;/code&gt;还有啥意义啊！文档也提到了，一般用户只需用到&lt;code&gt;setup&lt;/code&gt;和&lt;code&gt;teardown&lt;/code&gt;就够了，其他的 hook 是给 MiniTest 拓展用的。&lt;/p&gt;

&lt;p&gt;前面说了，MiniTest 兼容并收，即可用 Test::Unit 风格，也可用 Rspec 风格，下面就改用 Rspec 风格写上面的例子：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'minitest/spec'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'minitest/autorun'&lt;/span&gt;

&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;"TestMyLife"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
 &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;People&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"test_sleep"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
     &lt;span class="n"&gt;assert_equal&lt;/span&gt;   &lt;span class="s2"&gt;"zzZ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@me.sleep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"I don't sleep well "&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;看出不同了么？Rspec 风格就是用 describe 替换掉 class，用 it 替换掉测试方法，就是把对象风格的测试用例，变为了 Rake 这样的 DSL 了。注意前面要添加&lt;code&gt;require 'minitest/spec'&lt;/code&gt;，让 MiniTest 知道现在是 Rspec 风格的测试。&lt;/p&gt;

&lt;p&gt;事实上，在 Rspec 风格中，有人会追求用 &lt;strong&gt;Expectations&lt;/strong&gt; 代替 &lt;strong&gt;Assertions&lt;/strong&gt; ，就是写&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vi"&gt;@me.sleep.must_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"zzZ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"I don't sleep well "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而不是&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;assert_equal&lt;/span&gt;   &lt;span class="s2"&gt;"zzZ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@me.sleep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"I don't sleep well "&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不过这个看个人的口味啦。如果你对此有兴趣，看看这个 MiniTest 的 cheet sheet：
&lt;a href="http://danwin.com/2013/03/ruby-minitest-cheat-sheet/" rel="nofollow" target="_blank"&gt;http://danwin.com/2013/03/ruby-minitest-cheat-sheet/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="运行测试"&gt;运行测试&lt;/h2&gt;
&lt;p&gt;哎呀，啰啰嗦嗦说了一大堆，好像没讲明白如何运行这些测试呢。&lt;/p&gt;

&lt;p&gt;其实很简单，直接用 ruby 运行吧。&lt;code&gt;ruby test_file.rb&lt;/code&gt;即可。如果要运行多个测试，写一个脚本好了。
不过大家都是用 rake 来运行测试的，事实上 rake 也集成了运行测试的功能。&lt;/p&gt;

&lt;p&gt;看看下面的 Rakefile 片段：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Rake&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TestTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="c1"&gt;# libs表示要添加到$LOAD_PATH(就是加载ruby文件的搜索路径)的文件夹&lt;/span&gt;
  &lt;span class="c1"&gt;# 默认是"lib"，现在再添加"test"&lt;/span&gt;
  &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;libs&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt;
  &lt;span class="c1"&gt;# 要运行的测试文件的特征。匹配以test_开头的所有文件&lt;/span&gt;
  &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'test/**/test_*.rb'&lt;/span&gt; 
  &lt;span class="c1"&gt;# 不输出测试文件的信息&lt;/span&gt;
  &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verbose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后运行&lt;code&gt;rake test&lt;/code&gt;就能运行测试了。如果你设置&lt;code&gt;task :default =&amp;gt; :test&lt;/code&gt;，那么仅需&lt;code&gt;rake&lt;/code&gt;就能运行默认的任务 - 测试了。
BTW，通过指定&lt;code&gt;rake test TEST=xx&lt;/code&gt;，还可以只运行指定文件哦，当一个项目中包含的测试比较多时，只运行相关文件能省下许多时间。&lt;/p&gt;
&lt;h2 id="进阶功能"&gt;进阶功能&lt;/h2&gt;
&lt;p&gt;除了前面提到的常用功能，MiniTest 还提供了其他进阶功能，比如：&lt;/p&gt;
&lt;h3 id="Benchmark"&gt;Benchmark&lt;/h3&gt;
&lt;p&gt;还是用代码做介绍吧。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'minitest/autorun'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'minitest/benchmark'&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# 需要继承自Benchmark类&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestBenchmark&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MiniTest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Benchmark&lt;/span&gt;
  &lt;span class="c1"&gt;# 所有函数以bench_开头&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bench_algorithm&lt;/span&gt;
    &lt;span class="n"&gt;validation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;proc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;time cost: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;assert_performance&lt;/span&gt; &lt;span class="n"&gt;validation&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;setup_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ary&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bench_constant&lt;/span&gt;
    &lt;span class="c1"&gt;# 常数&lt;/span&gt;
    &lt;span class="n"&gt;assert_performance_constant&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; 
      &lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;setup_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;length&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bench_logarithmic&lt;/span&gt;
    &lt;span class="c1"&gt;# 查找时间复杂度与其说是log的，不如说是n&lt;/span&gt;
    &lt;span class="n"&gt;assert_performance_logarithmic&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;setup_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; 
        &lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt; &lt;span class="mi"&gt;10001&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bench_linear&lt;/span&gt;
    &lt;span class="c1"&gt;# 线性&lt;/span&gt;
    &lt;span class="n"&gt;assert_performance_linear&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;setup_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;ary&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort!&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bench_power&lt;/span&gt;
    &lt;span class="c1"&gt;# n^2&lt;/span&gt;
    &lt;span class="n"&gt;assert_performance_power&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;setup_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;shuffle!&lt;/span&gt;
      &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;ary&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ary&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bench_exponent&lt;/span&gt;
    &lt;span class="c1"&gt;# 指数&lt;/span&gt;
    &lt;span class="n"&gt;assert_performance_exponential&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MiniTest 支持 Benchmark 的测试，你可以测试函数的时间复杂度。这些断言接受两个参数，一个是精确度，另一个是要运行的 block。当然你也可以自定义精确度的计算方式，正如第一个&lt;code&gt;bench_algorithm&lt;/code&gt;所示。（虽然在那里我只是把输入和运行时间打印出来。）另外你也可以自定义参数的范围，默认条件下是从 1 到 10000，按 10 倍增长。&lt;/p&gt;

&lt;p&gt;用 Rspec 风格写 Benchmark 也是可能的，具体看文档。
&lt;a href="http://docs.seattlerb.org/minitest/Minitest/BenchSpec.html" rel="nofollow" target="_blank"&gt;http://docs.seattlerb.org/minitest/Minitest/BenchSpec.html&lt;/a&gt;&lt;/p&gt;
&lt;h3 id="Mock"&gt;Mock&lt;/h3&gt;
&lt;p&gt;有些时候，测试代码中可能会有这样的调用：它们消耗大把大把时间，占了单元测试的大部分时间；或者会带来不可逆的副作用，比如往远程数据库中添加数据，而你又不能每次执行都清空数据库。
这时候，我们应该怎么办？把调用标记为“FIXME”，然后交由维护的程序员头疼去？
在软件测试中，我们可以使用 Mock 来解决这个问题。我们不需要真的做这个调用，而是返回一个预期的值，交由要测试的方法进行处理。这样，我们无需进行完整的调用，就可以以合理的输入来测试方法。&lt;/p&gt;

&lt;p&gt;MiniTest 也集成了 Mock 的功能。一如既往，我还是直接 show you the code：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'minitest/autorun'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestMock&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;MiniTest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Test&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;setup&lt;/span&gt;
    &lt;span class="vi"&gt;@badman&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MiniTest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="c1"&gt;# expect :method_name, retval, args=[]&lt;/span&gt;
    &lt;span class="c1"&gt;#@badman.expect(:destroy_my_computer, true, [String])&lt;/span&gt;
    &lt;span class="vi"&gt;@badman.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:destroy_my_computer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="vi"&gt;@goodman&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;MiniTest&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Mock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
    &lt;span class="vi"&gt;@goodman.expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:destroy_my_computer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_mock&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@badman.destroy_my_computer&lt;/span&gt;
    &lt;span class="n"&gt;assert_equal&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@goodman.destroy_my_computer&lt;/span&gt;
    &lt;span class="c1"&gt;#assert_equal true, @badman.destroy_my_computer('brutally')&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所有 Mock 的实例都有一个&lt;code&gt;expect&lt;/code&gt;方法，接受:method_name, retval, args 这三个参数。其中 args 是输入参数数组，表示允许的输入范围。而 retval 是对应的返回值。&lt;/p&gt;

&lt;p&gt;MiniTest 还有其他一些功能我没有介绍，比如允许第三方插件自定义 test reporter 等等，如果需要，就阅读文档 + 搜索一下吧。&lt;/p&gt;</description>
      <author>spacewander</author>
      <pubDate>Mon, 08 Dec 2014 09:22:06 +0800</pubDate>
      <link>https://ruby-china.org/topics/23074</link>
      <guid>https://ruby-china.org/topics/23074</guid>
    </item>
    <item>
      <title>推荐一个监控进程情况的库（不是框架）？</title>
      <description>&lt;p&gt;在写一个工具，其中需要实现监控指定进程的功能。
看过了&lt;a href="https://github.com/mojombo/god" rel="nofollow" target="_blank" title=""&gt;god&lt;/a&gt;和&lt;a href="https://github.com/kostya/eye" rel="nofollow" target="_blank" title=""&gt;eye&lt;/a&gt;，感觉这些是框架，对于我的需求太过于复杂。&lt;/p&gt;

&lt;p&gt;所以现在来问了，求推荐一个监控进程情况的库，具有以下四个功能：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;返回当前所有的进程（类似于 ps -A）&lt;/li&gt;
&lt;li&gt;判断指定 pid/进程名的进程是否正在运行&lt;/li&gt;
&lt;li&gt;监控指定 pid/进程名的进程，当它被创建或结束时，发送一个消息。&lt;/li&gt;
&lt;li&gt;返回指定 pid/进程名的进程的运行时间&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;对于适用平台方面，仅需要满足 Linux 即可。&lt;/p&gt;

&lt;p&gt;append：
为了安装方便，希望是 ruby gem。&lt;/p&gt;</description>
      <author>spacewander</author>
      <pubDate>Thu, 20 Nov 2014 18:27:10 +0800</pubDate>
      <link>https://ruby-china.org/topics/22782</link>
      <guid>https://ruby-china.org/topics/22782</guid>
    </item>
    <item>
      <title>向 RubyGems 提交了一个未完成的 gem……</title>
      <description>&lt;p&gt;这下 &lt;strong&gt;糗大了&lt;/strong&gt;  &lt;img title=":tired_face:" alt="😫" src="https://twemoji.ruby-china.com/2/svg/1f62b.svg" class="twemoji"&gt;&lt;/p&gt;

&lt;p&gt;刚刚看了下已经有 27 个 download 了……请告诉我这些都是机器人干的……这样我内心好舒服些。
我已经在 README 中声明该 gem 还在 under construction，发生什么问题不要来找我……&lt;/p&gt;</description>
      <author>spacewander</author>
      <pubDate>Thu, 30 Oct 2014 00:10:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/22347</link>
      <guid>https://ruby-china.org/topics/22347</guid>
    </item>
    <item>
      <title>今天被各种 Markdown 方言给坑了……感觉对 Markdown 累觉不爱</title>
      <description>&lt;p&gt;原本在环境 A 里面看上去好好的 Markdown 格式，换到环境 B 就出了瑕疵。
以后就只能用各个平台都兼容的核心最小化的 Markdown 格式么？
感觉累觉不爱了……&lt;/p&gt;</description>
      <author>spacewander</author>
      <pubDate>Fri, 26 Sep 2014 16:21:37 +0800</pubDate>
      <link>https://ruby-china.org/topics/21736</link>
      <guid>https://ruby-china.org/topics/21736</guid>
    </item>
    <item>
      <title>Rails 中如何实现 “忘了我” 的功能？</title>
      <description>&lt;p&gt;一般网站在登录的时候，都会提供一个“记住我”的选项，如果选中该选项，下次就不用重新登录了。&lt;/p&gt;

&lt;p&gt;在 Rails 里面实现“记住我”，最简单的办法是设置&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;session_store&lt;/span&gt; &lt;span class="ss"&gt;:cookie_store&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;expire_after: &lt;/span&gt;&lt;span class="c1"&gt;# 一段相当长的时间&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样 Rails 就会在浏览器里面设置一个要过一段相当长的时间才会过期的 cookie。那么下次访问的时候，一旦检测到这个 cookie 的存在，就不用重新输入密码了。代价是，忘记密码的可能性增加了……&lt;/p&gt;

&lt;p&gt;不过，让我们看下反面的问题，如果用户不勾选那个“记住我”，那么怎么来实现 &lt;strong&gt;忘了我&lt;/strong&gt; 这个功能呢？&lt;/p&gt;

&lt;p&gt;&lt;code&gt;session_store&lt;/code&gt;的设置是全局的，而且&lt;code&gt;session&lt;/code&gt;类没有提供&lt;code&gt;expires&lt;/code&gt;的设置。&lt;code&gt;cookie&lt;/code&gt;倒是提供了，不过虽然 session 默认是用 cookie 实现的，但是&lt;code&gt;cookie&lt;/code&gt;和&lt;code&gt;session&lt;/code&gt;又不能混用……&lt;/p&gt;

&lt;p&gt;另外一个方法是设置一个&lt;code&gt;session[last_login]&lt;/code&gt;，用它来保留上次访问的时间。但是这么一来，每次检查&lt;code&gt;session&lt;/code&gt;里面的内容时，都得检查&lt;code&gt;session[last_login]&lt;/code&gt;，这样做要改动很多地方，而且不易维护（除非把&lt;code&gt;session&lt;/code&gt;包装成 Session 类）。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;所以在这里问一下大家，还有什么办法可以动态设置 session 的过期时间的？&lt;/strong&gt;&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;BTW，Ruby-china 的编辑框的 markdown 解析有点问题……只有&lt;code&gt;**粗体**&lt;/code&gt;左边是空格的情况下才能 &lt;strong&gt;加粗&lt;/strong&gt;，否则就不能&lt;strong&gt;加粗&lt;/strong&gt;。同样的，&lt;code&gt;*斜体*&lt;/code&gt;、&lt;code&gt;~~删除线~~&lt;/code&gt;也是这样&lt;/p&gt;</description>
      <author>spacewander</author>
      <pubDate>Tue, 23 Sep 2014 22:25:01 +0800</pubDate>
      <link>https://ruby-china.org/topics/21691</link>
      <guid>https://ruby-china.org/topics/21691</guid>
    </item>
  </channel>
</rss>
