Add rspec tests for lib.
diff --git a/.gitignore b/.gitignore
index ebf7215..e2546cf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,10 +2,11 @@
*.gem
*.rbc
/.config
-/coverage/
+/coverage
/InstalledFiles
/pkg/
/spec/reports/
+/spec/examples.txt
/test/tmp/
/test/version_tmp/
/tmp/
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..83e16f8
--- /dev/null
+++ b/.rspec
@@ -0,0 +1,2 @@
+--color
+--require spec_helper
diff --git a/.simplecov b/.simplecov
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.simplecov
diff --git a/Gemfile.lock b/Gemfile.lock
index 1a8200c..b75a4c4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -10,6 +10,7 @@
GEM
remote: https://rubygems.org/
specs:
+ addressable (2.3.8)
ast (2.1.0)
astrolabe (1.3.1)
parser (~> 2.2)
@@ -17,8 +18,14 @@
coderay (1.1.0)
commander (4.3.5)
highline (~> 1.7.2)
+ crack (0.4.2)
+ safe_yaml (~> 1.0.0)
+ diff-lcs (1.2.5)
+ docile (1.1.5)
exponential-backoff (0.0.2)
+ hashdiff (0.2.2)
highline (1.7.8)
+ json (1.8.3)
method_source (0.8.2)
mini_portile (0.6.2)
nokogiri (1.6.6.2)
@@ -33,6 +40,19 @@
slop (~> 3.4)
rainbow (2.0.0)
rake (10.4.2)
+ rspec (3.3.0)
+ rspec-core (~> 3.3.0)
+ rspec-expectations (~> 3.3.0)
+ rspec-mocks (~> 3.3.0)
+ rspec-core (3.3.2)
+ rspec-support (~> 3.3.0)
+ rspec-expectations (3.3.1)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.3.0)
+ rspec-mocks (3.3.2)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.3.0)
+ rspec-support (3.3.0)
rubocop (0.34.2)
astrolabe (~> 1.3)
parser (>= 2.2.2.5, < 3.0)
@@ -40,7 +60,17 @@
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.4)
ruby-progressbar (1.7.5)
+ safe_yaml (1.0.4)
+ simplecov (0.10.0)
+ docile (~> 1.1.0)
+ json (~> 1.8)
+ simplecov-html (~> 0.10.0)
+ simplecov-html (0.10.0)
slop (3.6.0)
+ webmock (1.22.1)
+ addressable (>= 2.3.6)
+ crack (>= 0.3.2)
+ hashdiff
PLATFORMS
ruby
@@ -51,7 +81,10 @@
mathnet-crawler!
pry (~> 0.10)
rake (~> 10.0)
+ rspec (~> 3.3.0)
rubocop (~> 0.34.2)
+ simplecov (~> 0.10.0)
+ webmock (~> 1.22.1)
BUNDLED WITH
1.10.6
diff --git a/Rakefile b/Rakefile
index 30f4443..4b701be 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,6 +1,8 @@
require 'bundler/gem_tasks'
require 'rubocop/rake_task'
+require 'rspec/core/rake_task'
RuboCop::RakeTask.new
+RSpec::Core::RakeTask.new(:spec)
-task default: [:rubocop]
+task default: [:rubocop, :spec]
diff --git a/mathnet-crawler.gemspec b/mathnet-crawler.gemspec
index 7aac24d..c21f659 100644
--- a/mathnet-crawler.gemspec
+++ b/mathnet-crawler.gemspec
@@ -38,4 +38,7 @@
spec.add_development_dependency 'rubocop', '~> 0.34.2'
spec.add_development_dependency 'pry', '~> 0.10'
spec.add_development_dependency 'byebug', '~> 6.0'
+ spec.add_development_dependency 'rspec', '~> 3.3.0'
+ spec.add_development_dependency 'simplecov', '~> 0.10.0'
+ spec.add_development_dependency 'webmock', '~> 1.22.1'
end
diff --git a/spec/crawler_spec.rb b/spec/crawler_spec.rb
new file mode 100644
index 0000000..e8332c9
--- /dev/null
+++ b/spec/crawler_spec.rb
@@ -0,0 +1,280 @@
+require 'mathnet/crawler'
+require 'webmock/rspec'
+
+Library = Mathnet::Crawler::Library
+Journal = Mathnet::Crawler::Journal
+Issue = Mathnet::Crawler::Issue
+Article = Mathnet::Crawler::Article
+
+RSpec.describe Journal, '#list' do
+ before :each do
+ @download_link = 'www.mathnet.ru/ej.phtml'
+ end
+
+ it 'single journal' do
+ single_journal = %{
+ <table><tbody><tr>
+ <td><a name="JPUBLISHER8"><b><i>Российская академия наук, Отделение математических наук</i></b></a></td>
+ </tr>
+ <tr>
+ <td><a class="SLink" title="Алгебра и анализ" href="/php/journal.phtml?jrnid=aa&option_lang=rus">Алгебра и анализ</a></td>
+ <td>Свободный доступ к полным текстам предоставляется по прошествии трех лет с момента выхода соответствующего номера журнала</td>
+ </tr></tbody></table>
+ }
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: single_journal, headers: {})
+ journals = Journal.list Library.new
+ expect(journals).to be_a Array
+ expect(journals.size).to eq 1
+ expect(journals[0].title).to eq 'Алгебра и анализ'
+ expect(journals[0].children_url).to eq '/php/archive.phtml?wshow=contents&jrnid=aa&option_lang=rus'
+ end
+
+ it 'no journals' do
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: '', headers: {})
+ journals = Journal.list Library.new
+ expect(journals).to be_a Array
+ expect(journals).to eq []
+ end
+
+ it 'raise socket error' do
+ stub_request(:get, @download_link).
+ to_raise SocketError
+ expect { Journal.list Library.new } .to raise_error SocketError
+ end
+
+ it 'raise server exception' do
+ stub_request(:get, @download_link).
+ to_return(status: 400, body: '', headers: {})
+ expect { Journal.list Library.new } .to raise_error Net::HTTPServerException
+ end
+
+end
+
+RSpec.describe Issue, '#list' do
+
+ before :each do
+ tag = {'title' => 'Test', 'href' => '/php/journal.phtml?jrnid=aa'}
+ @journal = Journal.new Library.new, tag
+ @download_link = 'www.mathnet.ru/php/archive.phtml?jrnid=aa&wshow=contents'
+ end
+
+ it 'single issue' do
+ single_journal = %{
+ <table><tbody><tr>
+ <td"7"><br>Дискретный анализ и исследование операций</td>
+ </tr>
+ <tr><td>
+ <img align="absmiddle" src="/gifs/wvols.gif" border="0"> том 22, 2015
+ / <a class="SLink" target="_top" href="/php/contents.phtml?jrnid=da&wshow=aindex&year=2015&volume=22&volume_alt=&option_lang=rus">Именной указатель</a>
+ </td></tr>
+ <tr>
+ <td class="series"></td>
+ <td title="Дискретн. анализ и исслед. опер., том 22, 2015, номер 1">
+ <a title="Дискретн. анализ и исслед. опер., том 22, 2015, номер 1" class="SLink" href="/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2015&volume=22&volume_alt=&issue=1&issue_alt=&option_lang=rus"><nobr>1</nobr></a>
+ </td>
+ <img align="absmiddle" src="/gifs/wvols.gif" border="0"> том 21, 2014
+ / <a class="SLink" target="_top" href="Дискретн. анализ и исслед. опер., том 22, 2015, номер 1">Именной указатель</a></td>
+ </tr>
+ </tbody></table>
+ }
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: single_journal, headers: {})
+ issues = Issue.list @journal
+ expect(issues).to be_a Array
+ expect(issues.size).to eq 1
+ expect(issues[0].title).to eq 'Дискретн. анализ и исслед. опер., том 22, 2015, номер 1'
+ expect(issues[0].children_url).to eq '/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2015&volume=22&volume_alt=&issue=1&issue_alt=&option_lang=rus'
+ end
+
+ it '3 issues' do
+ single_journal = %{
+ <table><tbody>
+ <tr>
+ <td title="Дискретн. анализ и исслед. опер., том 22, 2015, номер 1">
+ <a title="Дискретн. анализ и исслед. опер., том 22, 2015, номер 1" class="SLink" href="/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2015&volume=22&volume_alt=&issue=1&issue_alt=&option_lang=rus"><nobr>1</nobr></a>
+ </td>
+ <img align="absmiddle" src="/gifs/wvols.gif" border="0"> том 21, 2014
+ / <a class="SLink" target="_top" href="Дискретн. анализ и исслед. опер., том 22, 2015, номер 1">Именной указатель</a></td>
+ <td title="Дискретн. анализ и исслед. опер., том 19, 2012, номер 1 Доступны полные тексты статей"class="issue_with_corner" align="center">
+ <a title="Дискретн. анализ и исслед. опер., том 19, 2012, номер 1 Доступны полные тексты статей" class="SLink" href="/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2012&volume=19&volume_alt=&issue=1&issue_alt=&option_lang=rus"><nobr>1</nobr></a>
+ </td>
+ </tr>
+ <tr>
+ <td title="Дискретн. анализ и исслед. опер., том 18, 2011, номер 1 Доступны полные тексты статей" class="issue_with_corner" align="center">
+ <a title="Дискретн. анализ и исслед. опер., том 18, 2011, номер 1 Доступны полные тексты статей" class="SLink" href="/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2011&volume=18&volume_alt=&issue=1&issue_alt=&option_lang=rus"><nobr>1</nobr></a>
+ </td>
+ </tr>
+ </tbody></table>
+ }
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: single_journal, headers: {})
+ issues = Issue.list @journal
+ expect(issues).to be_a Array
+ expect(issues.size).to eq 3
+ expect(issues[0].title).to eq 'Дискретн. анализ и исслед. опер., том 22, 2015, номер 1'
+ expect(issues[0].children_url).to eq '/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2015&volume=22&volume_alt=&issue=1&issue_alt=&option_lang=rus'
+ expect(issues[1].title).to eq 'Дискретн. анализ и исслед. опер., том 19, 2012, номер 1 Доступны полные тексты статей'
+ expect(issues[1].children_url).to eq '/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2012&volume=19&volume_alt=&issue=1&issue_alt=&option_lang=rus'
+ expect(issues[2].title).to eq 'Дискретн. анализ и исслед. опер., том 18, 2011, номер 1 Доступны полные тексты статей'
+ expect(issues[2].children_url).to eq '/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2011&volume=18&volume_alt=&issue=1&issue_alt=&option_lang=rus'
+
+ end
+
+ it 'no issues' do
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: '', headers: {})
+ issues = Issue.list @journal
+ expect(issues).to be_a Array
+ expect(issues).to eq []
+ end
+
+ it 'raise socket error' do
+ stub_request(:get, @download_link).
+ to_raise SocketError
+ expect { Issue.list @journal } .to raise_error SocketError
+ end
+
+ it 'raise server exception' do
+ stub_request(:get, @download_link).
+ to_return(status: 400, body: '', headers: {})
+ expect { Issue.list @journal } .to raise_error Net::HTTPServerException
+ end
+
+end
+
+RSpec.describe Article, '#list' do
+
+ before :each do
+ journal_tag = {'title' => 'Test', 'href' => '/php/journal.phtml?jrnid=aa'}
+ journal = Journal.new Library.new, journal_tag
+ issues_tag = {'title' => 'Test issue 1', 'href' => '/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2015&volume=22&volume_alt=&issue=1&issue_alt=&option_lang=rus'}
+ @issue = Issue.new journal, issues_tag
+ @download_link = 'www.mathnet.ru/php/archive.phtml?issue=1&issue_alt=&jrnid=da&option_lang=rus&series=0&volume=22&volume_alt=&wshow=issue&year=2015'
+ end
+
+ it 'single issue' do
+ single_journal = %{
+ <table><tbody><tr>
+ <td valign="top" width="11">
+ <img title="Доступен полный текст статьи" align="absmiddle" src="/gifs/wvolsa.gif" border="0">
+ </td>
+ <td colspan="2" width="90%" valign="top" align="left">
+ <a class="SLink" href="/rus/da763">Алгоритм ветвей и границ для задачи конкурентного размещения предприятий с предписанным выбором поставщиков</a><br>В. Л. Береснев, А. А. Мельников
+ </td>
+ <td valign="top" align="right">3</td>
+ </tr></tbody></table>
+ }
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: single_journal, headers: {})
+ articles = Article.list @issue
+ expect(articles).to be_a Array
+ expect(articles.size).to eq 1
+ expect(articles[0].title).to eq 'Алгоритм ветвей и границ для задачи конкурентного размещения предприятий с предписанным выбором поставщиков'
+ expect(articles[0].children_url).to eq '/rus/da763'
+ end
+
+ it '3 issues' do
+ single_journal = %{
+ <table><tbody>
+ <tr>
+ <td valign="top" width="11">
+ <img title="Доступен полный текст статьи" align="absmiddle" src="/gifs/wvolsa.gif" border="0">
+ </td>
+ <td colspan="2" width="90%" valign="top" align="left">
+ <a class="SLink" href="/rus/da766">Пороговое свойство квадратичных булевых функций</a><br>Н. А. Коломеец
+ </td>
+ <td valign="top" align="right">52</td>
+ </tr>
+ <tr>
+ <td valign="top" width="11">
+ <img title="Доступен полный текст статьи" align="absmiddle" src="/gifs/wvolsa.gif" border="0">
+ </td>
+ <td colspan="2" width="90%" valign="top" align="left">
+ <a class="SLink" href="/rus/da767">Функция Шеннона быстрого вычисления сложности по Арнольду двоичных слов длины <nobr><span class="MathJax_Preview" style="color: inherit;"></span><span class="MathJax" id="MathJax-Element-1-Frame" style=""><nobr><span class="math" id="MathJax-Span-1" role="math" style="width: 1.253em; display: inline-block;"><span style="display: inline-block; position: relative; width: 1.044em; height: 0px; font-size: 120%;"><span style="position: absolute; clip: rect(0.107em, 1000.003em, 1.148em, -999.997em); top: -0.987em; left: 0.003em;"><span class="mrow" id="MathJax-Span-2"><span class="msubsup" id="MathJax-Span-3"><span style="display: inline-block; position: relative; width: 0.992em; height: 0px;"><span style="position: absolute; clip: rect(3.18em, 1000.003em, 4.169em, -999.997em); top: -4.008em; left: 0.003em;"><span class="mn" id="MathJax-Span-4" style="font-family: MathJax_Main;">2</span><span style="display: inline-block; width: 0px; height: 4.013em;"></span></span><span style="position: absolute; top: -4.424em; left: 0.523em;"><span class="mi" id="MathJax-Span-5" style="font-size: 70.7%; font-family: MathJax_Math-italic;">n</span><span style="display: inline-block; width: 0px; height: 4.013em;"></span></span></span></span></span><span style="display: inline-block; width: 0px; height: 0.992em;"></span></span></span><span style="border-left-width: 0.003em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 1.003em; vertical-align: -0.059em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-1">2^n</script></nobr> для произвольных значений <nobr><span class="MathJax_Preview" style="color: inherit;"></span><span class="MathJax" id="MathJax-Element-2-Frame" style=""><nobr><span class="math" id="MathJax-Span-6" role="math" style="width: 0.784em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.628em; height: 0px; font-size: 120%;"><span style="position: absolute; clip: rect(1.93em, 1000.003em, 2.659em, -999.997em); top: -2.497em; left: 0.003em;"><span class="mrow" id="MathJax-Span-7"><span class="mi" id="MathJax-Span-8" style="font-family: MathJax_Math-italic;">n</span></span><span style="display: inline-block; width: 0px; height: 2.503em;"></span></span></span><span style="border-left-width: 0.003em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.691em; vertical-align: -0.059em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-2">n</script></nobr></a><br>Ю. В. Мерекин
+ </td>
+ <td valign="top" align="right">59</td>
+ </tr>
+ <tr>
+ <td valign="top" width="11">
+ <img title="Доступен полный текст статьи" align="absmiddle" src="/gifs/wvolsa.gif" border="0">
+ </td>
+ <td colspan="2" width="90%" valign="top" align="left">
+ <a class="SLink" href="/rus/da768">Совершенные <nobr><span class="MathJax_Preview" style="color: inherit;"></span><span class="MathJax" id="MathJax-Element-3-Frame" style=""><nobr><span class="math" id="MathJax-Span-9" role="math" style="width: 0.628em; display: inline-block;"><span style="display: inline-block; position: relative; width: 0.523em; height: 0px; font-size: 120%;"><span style="position: absolute; clip: rect(1.878em, 1000.003em, 2.867em, -999.997em); top: -2.706em; left: 0.003em;"><span class="mrow" id="MathJax-Span-10"><span class="mn" id="MathJax-Span-11" style="font-family: MathJax_Main;">2</span></span><span style="display: inline-block; width: 0px; height: 2.711em;"></span></span></span><span style="border-left-width: 0.003em; border-left-style: solid; display: inline-block; overflow: hidden; width: 0px; height: 0.941em; vertical-align: -0.059em;"></span></span></nobr></span><script type="math/tex" id="MathJax-Element-3">2</script></nobr>-раскраски бесконечных циркулянтных графов со сплошным набором дистанций</a><br>О. Г. Паршина
+ </td>
+ <td valign="top" align="right">76</td>
+ </tr>
+ </tbody></table>
+ }
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: single_journal, headers: {})
+ articles = Article.list @issue
+ expect(articles).to be_a Array
+ expect(articles.size).to eq 3
+ expect(articles[0].title).to eq 'Пороговое свойство квадратичных булевых функций'
+ expect(articles[0].children_url).to eq '/rus/da766'
+ expect(articles[1].title).to eq 'Функция Шеннона быстрого вычисления сложности по Арнольду двоичных слов длины 2n2^n для произвольных значений nn'
+ expect(articles[1].children_url).to eq '/rus/da767'
+ expect(articles[2].title).to eq 'Совершенные 22-раскраски бесконечных циркулянтных графов со сплошным набором дистанций'
+ expect(articles[2].children_url).to eq '/rus/da768'
+ end
+
+ it 'no issues' do
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: '', headers: {})
+ articles = Article.list @issue
+ expect(articles).to be_a Array
+ expect(articles).to eq []
+ end
+
+ it 'raise socket error' do
+ stub_request(:get, @download_link).
+ to_raise SocketError
+ expect { Article.list @issue } .to raise_error SocketError
+ end
+
+ it 'raise server exception' do
+ stub_request(:get, @download_link).
+ to_return(status: 400, body: '', headers: {})
+ expect { Article.list @issue } .to raise_error Net::HTTPServerException
+ end
+
+end
+
+RSpec.describe Article, '#full_text' do
+
+ before :each do
+ journal_tag = {'title' => 'Test', 'href' => '/php/journal.phtml?jrnid=aa'}
+ journal = Journal.new Library.new, journal_tag
+ issues_tag = {'title' => 'Test issue 1', 'href' => '/php/archive.phtml?jrnid=da&wshow=issue&series=0&year=2015&volume=22&volume_alt=&issue=1&issue_alt=&option_lang=rus'}
+ issue = Issue.new journal, issues_tag
+ article_tag = double("Article Tag", :text => 'Article')
+ allow(article_tag).to receive(:[]).with('title').and_return 'Test article 1'
+ allow(article_tag).to receive(:[]).with('href').and_return '/rus/da766'
+ @article = Article.new issue, article_tag
+ @download_link = 'www.mathnet.ru/rus/da766'
+ @full_text_url = '/php/getFT.phtml?jrnid=da&paperid=763&what=fullt&option_lang=rus'
+ @full_text_link = "www.mathnet.ru#{@full_text_url}"
+ end
+
+ it 'single issue' do
+ single_journal = %{
+ <a class="SLink" href="#{@full_text_url}">PDF файл</a>
+ }
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: single_journal, headers: {})
+ stub_request(:get, @full_text_link).
+ to_return(status: 200, body: single_journal, headers: {})
+ @article.full_text {}
+ end
+
+ it 'no full test' do
+ single_journal = %{}
+ stub_request(:get, @download_link).
+ to_return(status: 200, body: single_journal, headers: {})
+ expect { @article.full_text {} } .to raise_error ArgumentError
+ end
+
+end
+
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..b12cd84
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,64 @@
+require 'simplecov'
+SimpleCov.start
+SimpleCov.command_name "features" + (ENV['TEST_ENV_NUMBER'] || '')
+
+# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
+RSpec.configure do |config|
+ config.expect_with :rspec do |expectations|
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
+ end
+
+ config.mock_with :rspec do |mocks|
+ mocks.verify_partial_doubles = true
+ end
+
+ # These two settings work together to allow you to limit a spec run
+ # to individual examples or groups you care about by tagging them with
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
+ # get run.
+ config.filter_run :focus
+ config.run_all_when_everything_filtered = true
+
+ # Allows RSpec to persist some state between runs in order to support
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
+ # you configure your source control system to ignore this file.
+ config.example_status_persistence_file_path = 'spec/examples.txt'
+
+ # Limits the available syntax to the non-monkey patched syntax that is
+ # recommended. For more details, see:
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
+ config.disable_monkey_patching!
+
+ # This setting enables warnings. It's recommended, but in some cases may
+ # be too noisy due to issues in dependencies.
+ config.warnings = true
+
+ # Many RSpec users commonly either run the entire suite or an individual
+ # file, and it's useful to allow more verbose output when running an
+ # individual spec file.
+ if config.files_to_run.one?
+ # Use the documentation formatter for detailed output,
+ # unless a formatter has already been configured
+ # (e.g. via a command-line flag).
+ config.default_formatter = 'doc'
+ end
+
+ # Print the 10 slowest examples and example groups at the
+ # end of the spec run, to help surface which specs are running
+ # particularly slow.
+ config.profile_examples = 10
+
+ # Run specs in random order to surface order dependencies. If you find an
+ # order dependency and want to debug it, you can fix the order by providing
+ # the seed, which is printed after each run.
+ # --seed 1234
+ config.order = :random
+
+ # Seed global randomization in this process using the `--seed` CLI option.
+ # Setting this allows you to use `--seed` to deterministically reproduce
+ # test failures related to randomization by passing the same `--seed` value
+ # as the one that triggered the failure.
+ Kernel.srand config.seed
+end