<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">
	<channel>
		<title>Author at Infinum</title>
		<atom:link href="https://infinum.com/blog/author/jan-varljen/feed/" rel="self" type="application/rss+xml" />
		<link></link>
		<description>Building digital products</description>
		<lastBuildDate>Fri, 24 Apr 2026 14:02:14 +0000</lastBuildDate>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>

					<item>
				<image>
					<url>8018https://infinum.com/uploads/2014/04/run-faster-ruby-on-rails-tests-0.webp</url>
				</image>
				<title>Run Faster Ruby on Rails Tests</title>
				<link>https://infinum.com/blog/run-faster-ruby-on-rails-tests/</link>
				<pubDate>Thu, 17 Apr 2014 12:21:00 +0000</pubDate>
				<dc:creator>Jan Varljen</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/run-faster-ruby-on-rails-tests/</guid>
				<description>
					<![CDATA[<p>Performing tests consumes precious time so we decided to do some tinkering to make our test suite load and execute faster.</p>
<p>The post <a href="https://infinum.com/blog/run-faster-ruby-on-rails-tests/">Run Faster Ruby on Rails Tests</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-202"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-92">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-95"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-93">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-94'
	>
	Doing software development with a Continuous Integration process involves a lot of automated testing. Doing tests consumes precious time so we decided to do some tinkering to make our test suite load and execute faster.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-98"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-96">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-97'
	>
	As your test suite grows, it takes longer to run the tests, and soon you have a problem because your test suite is running for over 10 minutes. Now you have two options: reduce the number of tests or optimize the test execution time.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-101"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-99">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-100'
	>
	Impulse speed</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-104"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-102"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-103">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/04/run-faster-ruby-on-rails-tests-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="292"
															width="700"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-107"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-105">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-106'
	>
	A few months ago, we wrote about how we do <a href="https://infinum.com/blog/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat/">Continuous Integration in Ruby on Rails</a>. Back then, a test suite for one of our projects (around 1400 tests) ran for about 7 minutes. Today, an even larger test suite (around 1700 tests) runs for 2 and a half minutes. How did we do it?</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-110"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-108">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-109'
	>
	The mighty Zeus</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-113"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-111">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-112'
	>
	Every time you call a rake task, your Rails application has to be loaded. The time it takes to load the application depends heavily on the size of the application and the number of gems the application is using. In our example, it was around 10 seconds. At first, 10 seconds doesn’t sound that bad, but when you realize you are calling rake tasks all the time and you have to wait for 10 seconds every time, you start to feel unproductive.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-116"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-114">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-115'
	>
	So we started using <a href="https://github.com/burke/zeus">Zeus</a>. Zeus speeds up loading time of your Rails application by <strong>preloading your application only once</strong> and then monitoring file changes in your application directory and doing reloads in the background. Now you can call a rake task with: <strong>Zeus rake task</strong> and it’ll take less than one second to start because the Rails application is already preloaded.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-119"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-117">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-118'
	>
	Running a large test suite with Zeus isn’t a big win (we cut off the first 10 seconds). It’s most useful when you’re doing <a href="http://en.wikipedia.org/wiki/Test-driven_development">TDD</a> because you run your tests numerous times while developing. If you have to wait 10 seconds every time, it’s just not doable.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-122"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-120">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-121'
	>
	Just take this simple model spec with 9 tests as an example:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-124"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">time</span><span class="token"> rspec spec/models/balance_spec.rb 
</span></span><span class="line"><span class="token" style="color: #6f42c1;">0m7.355s</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">time</span><span class="token"> zeus rspec spec/models/balance_spec.rb 
</span></span><span class="line"><span class="token" style="color: #6f42c1;">0m0.930s</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-127"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-125"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-126">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/04/run-faster-ruby-on-rails-tests-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="279"
															width="700"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Fig 1. Coming up to Warp 4!		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-130"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-128">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-129'
	>
	Spring maybe?</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-133"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-131">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-132'
	>
	With the latest release of <a href="http://edgeguides.rubyonrails.org/4_1_release_notes.html">Rails 4.1</a>, the Spring application preloader was introduced as a part of the standard Rails environment. The idea behind Spring is the same as behind the mighty Zeus – preload your Rails application to speed up development. We tried using Spring on our projects and it works almost equally awesome. We favor Zeus primarily because it’s noticeably faster (roughly 30% faster), but we are eagerly awaiting any future reversals.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-136"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-134">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-135'
	>
	Running tests in parallel</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-139"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-137">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-138'
	>
	The thing that actually makes a huge difference when running a large test suite is running tests in parallel. Modern CPUs have lots of cores, which makes utilizing those cores for testing very effective.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-142"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-140">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-141'
	>
	Luckily, there is a gem called <a href="https://github.com/grosser/parallel_tests">Parallel Tests</a> which does just that. The gem creates multiple test databases (one for each core) and then distributes all tests across those cores and runs them in parallel.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-145"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-143">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-144'
	>
	You can even combine parallel tests with Zeus, using a gem called <a href="https://github.com/sevos/zeus-parallel_tests">Zeus Parallel Tests</a>. With this combination, <strong>we reduced the running time of our test suite by over 50%</strong>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-147"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">time</span><span class="token"> rspec
</span></span><span class="line"><span class="token" style="color: #6f42c1;">1m50.843s</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">time</span><span class="token"> zeus parallel_rspec
</span></span><span class="line"><span class="token" style="color: #6f42c1;">0m52.924s</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-150"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-148"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-149">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/04/run-faster-ruby-on-rails-tests-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="279"
															width="700"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Fig 2. Approaching Warp 7!		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-153"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-151">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-152'
	>
	Mock, extract and refactor</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-156"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-154">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-155'
	>
	When a test is slow, it probably means that the model you’re testing is not optimized and you should be thinking about refactoring.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-159"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-157">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-158'
	>
	A typical antipattern is creating fat models with a lot of business logic and then wondering why tests are slow. It’s because you are testing things which don’t need to be tested (e.g. ActiveRecord) but mocked, and you’re needlessly hitting the database.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-162"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-160">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-161'
	>
	Let’s show this using a simple example:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-164"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">class</span><span class="token"> </span><span class="token" style="color: #6f42c1;">PriceList</span><span class="token"> </span><span class="token">&lt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">ActiveRecord</span><span class="token" style="color: #6f42c1;">::</span><span class="token" style="color: #6f42c1;">Base</span><span class="token">
</span></span><span class="line"><span class="token">  has_many </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">products</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">total_price</span><span class="token">
</span></span><span class="line"><span class="token">    products</span><span class="token">.</span><span class="token" style="color: #6f42c1;">sum</span><span class="token">(</span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">price</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-166"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">require</span><span class="token"> ’spec_helper’</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">describe </span><span class="token" style="color: #005cc5;">PriceList</span><span class="token"> </span><span class="token" style="color: #d73a49;">do</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #6f42c1;">let</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">price_list</span><span class="token">)</span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #6f42c1;">create</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">price_list</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">  describe ’</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">total_price’ do</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    before </span><span class="token" style="color: #d73a49;">do</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #6f42c1;">create</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">product</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">price_list</span><span class="token" style="color: #005cc5;">:</span><span class="token"> price_list</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">price</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">100</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">      </span><span class="token" style="color: #6f42c1;">create</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">product</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">price_list</span><span class="token" style="color: #005cc5;">:</span><span class="token"> price_list</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">price</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">200</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">    it </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #6f42c1;">expect</span><span class="token">(</span><span class="token">price_list</span><span class="token">.</span><span class="token" style="color: #6f42c1;">total_price</span><span class="token">)</span><span class="token">.</span><span class="token" style="color: #6f42c1;">to</span><span class="token"> </span><span class="token" style="color: #6f42c1;">eq</span><span class="token">(</span><span class="token" style="color: #005cc5;">300</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-168"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">time</span><span class="token"> rspec spec/model/price_list_spec.rb 
</span></span><span class="line"><span class="token" style="color: #6f42c1;">0m8.396s</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-171"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-169">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-170'
	>
	Now let’s try to refactor our model and extract that <strong>#total_price</strong> functionality to a separate class so we can test it in isolation:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-173"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">class</span><span class="token"> </span><span class="token" style="color: #6f42c1;">PriceSheet</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">total_price</span><span class="token">(</span><span class="token">items</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">    items</span><span class="token">.</span><span class="token" style="color: #6f42c1;">map</span><span class="token">(</span><span class="token" style="color: #d73a49;">&amp;</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">price</span><span class="token">)</span><span class="token">.</span><span class="token" style="color: #6f42c1;">inject</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">+</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-175"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">class</span><span class="token"> </span><span class="token" style="color: #6f42c1;">PriceList</span><span class="token"> </span><span class="token">&lt;</span><span class="token"> </span><span class="token" style="color: #6f42c1;">ActiveRecord</span><span class="token" style="color: #6f42c1;">::</span><span class="token" style="color: #6f42c1;">Base</span><span class="token">
</span></span><span class="line"><span class="token">  has_many </span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">products</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">def</span><span class="token"> </span><span class="token" style="color: #6f42c1;">total_price</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #005cc5;">PriceSheet</span><span class="token">.</span><span class="token" style="color: #d73a49;">new</span><span class="token">.</span><span class="token" style="color: #6f42c1;">total_price</span><span class="token">(</span><span class="token">products</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-177"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-ruby github-light" data-language="ruby" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token" style="color: #d73a49;">require</span><span class="token"> </span><span class="token" style="color: #005cc5;">File</span><span class="token">.</span><span class="token" style="color: #6f42c1;">expand_path</span><span class="token">(</span><span class="token" style="color: #032f62;">&quot;</span><span class="token" style="color: #032f62;">../../../lib/price_sheet.rb</span><span class="token" style="color: #032f62;">&quot;</span><span class="token">,</span><span class="token"> </span><span class="token" style="color: #005cc5;">__FILE__</span><span class="token">)</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">describe </span><span class="token" style="color: #005cc5;">PriceSheet</span><span class="token"> </span><span class="token" style="color: #d73a49;">do</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span><span class="line"><span class="token">  describe ’</span><span class="token" style="color: #6a737d;">#</span><span class="token" style="color: #6a737d;">total_price’ do</span><span class="token" style="color: #6a737d;">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6f42c1;">let</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">item_one</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #6f42c1;">double</span><span class="token">(</span><span class="token" style="color: #005cc5;">price</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">200</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">    </span><span class="token" style="color: #6f42c1;">let</span><span class="token">(</span><span class="token" style="color: #005cc5;">:</span><span class="token" style="color: #005cc5;">item_two</span><span class="token">)</span><span class="token"> </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #6f42c1;">double</span><span class="token">(</span><span class="token" style="color: #005cc5;">price</span><span class="token" style="color: #005cc5;">:</span><span class="token"> </span><span class="token" style="color: #005cc5;">100</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">    it </span><span class="token">{</span><span class="token"> </span><span class="token" style="color: #6f42c1;">expect</span><span class="token">(</span><span class="token" style="color: #005cc5;">PriceSheet</span><span class="token">.</span><span class="token" style="color: #d73a49;">new</span><span class="token">.</span><span class="token" style="color: #6f42c1;">total_price</span><span class="token">(</span><span class="token">[</span><span class="token">item_one</span><span class="token">,</span><span class="token"> item_two</span><span class="token">]</span><span class="token">)</span><span class="token">)</span><span class="token">.</span><span class="token" style="color: #6f42c1;">to</span><span class="token"> </span><span class="token" style="color: #6f42c1;">eq</span><span class="token">(</span><span class="token" style="color: #005cc5;">300</span><span class="token">)</span><span class="token"> </span><span class="token">}</span><span class="token">
</span></span><span class="line"><span class="token">  </span><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">end</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-179"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-code">
	<pre class="phiki language-shellscript github-light" data-language="shellscript" style="background-color: #fff;color: #24292e;"><code><span class="line"><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">time</span><span class="token"> rspec spec/lib/price_sheet_spec.rb 
</span></span><span class="line"><span class="token" style="color: #6f42c1;">0m1.530s</span><span class="token">
</span></span><span class="line"><span class="token" style="color: #d73a49;">time</span><span class="token"> zeus rspec spec/lib/price_sheet_spec.rb 
</span></span><span class="line"><span class="token" style="color: #6f42c1;">0m0.270s</span><span class="token">
</span></span><span class="line"><span class="token">
</span></span></code></pre></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-182"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-180">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-181'
	>
	Now we don’t need to require the <strong>spec_helper</strong> (which loads Rails), we can mock the items and avoid hitting the database.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-185"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-183"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-184">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/04/run-faster-ruby-on-rails-tests-4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="365"
															width="700"
										loading="lazy"
					 />
					</picture>

			<figcaption class="image__figcaption block-media__image-figcaption">
			Fig 3. Warp 9. Engage!		</figcaption>
	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-188"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-186">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-187'
	>
	We like this approach, not only because our tests are faster, but also because it drives us to write better code and avoid writing fat models.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-191"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-189">
	<h2	class='typography typography--size-52-default js-typography block-heading__heading'
	data-id='es-190'
	>
	Mocking external services</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-194"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-192">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-193'
	>
	One important thing to remember is &#8211; don’t let your tests access any external web services. There are several reasons why this is bad:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-197"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-195">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-196'
	>
	<li>It really slows down tests</li><li>Tests will fail if you don’t have internet connectivity</li><li>Hitting third party services will unnecessarily use API request limits</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-200"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-198">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-199'
	>
	This can be solved by disabling all remote connections in your tests, mocking the external service functionality and testing it in isolation. We use the <a href="https://github.com/bblimke/webmock">WebMock</a> gem for this.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/run-faster-ruby-on-rails-tests/">Run Faster Ruby on Rails Tests</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
					<item>
				<image>
					<url>7988https://infinum.com/uploads/2014/01/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat-0.webp</url>
				</image>
				<title>A Ruby on Rails Continuous Integration Process Using Github, Semaphore, CodeClimate and HipChat</title>
				<link>https://infinum.com/blog/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat/</link>
				<pubDate>Wed, 22 Jan 2014 00:59:00 +0000</pubDate>
				<dc:creator>Jan Varljen</dc:creator>
				<guid isPermaLink="false">https://infinum.com/the-capsized-eight/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat/</guid>
				<description>
					<![CDATA[<p>How our Rails team handles buggy code with testing and continuous integration using Github Semaphore, CodeClimate and HipChat.</p>
<p>The post <a href="https://infinum.com/blog/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat/">A Ruby on Rails Continuous Integration Process Using Github, Semaphore, CodeClimate and HipChat</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</description>
				<content:encoded>
					<![CDATA[<div
	class="wrapper"
	data-id="es-307"
	 data-animation-target='inner-items'>
		
			<div class="wrapper__inner">
			<div class="block-blog-content js-block-blog-content">
	
<div class="block-blog-content-sidebar" data-id="es-203">
	</div>

<div class="block-blog-content-main">
	
<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-206"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-204">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-205'
	>
	When you work on applications that your clients are actively using, you want to be 100% sure you don’t break something when deploying a new feature.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-209"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-207">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-208'
	>
	We all know the feeling when your ticketing system starts screaming at you with bug reports because you’ve deployed some buggy code and your application has started to misbehave. With that in mind, I’ll show you how our Ruby on Rails development team handles this with testing and a Continuous Integration process.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-212"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-210">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-211'
	>
	What is continuous integration?</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-215"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-213"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-214">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/01/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat-1.webp"
					class="image__img block-media__image-img"
					alt=""
										height="587"
															width="644"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-218"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-216">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-217'
	>
	<a href="http://en.wikipedia.org/wiki/Continuous_integration">Continuous Integration (CI)</a> is a software development practice where members of a team integrate their work as frequently as possible to reduce integration problems and code conflicts. Every push to a source code repository is verified by an automated build and a test suite to detect errors as quickly as possible. A good CI tool also has a good notification system which effectively notifies all the team members about conflicts and issues with their code.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-221"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-219">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-220'
	>
	Building a test suite</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-224"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-222">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-223'
	>
	First of all, to get started with any sort of Continuous Integration – <strong>you need to write tests</strong>. Without a test suite, it’s impossible to check if changes to a codebase broke something; well, at least in an automated way. You can always manually open every view, every form, and try every action in your application after you change something, but that’s hardly an efficient way to do it.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-227"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-225">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-226'
	>
	We mostly write <a href="http://guides.rubyonrails.org/testing.html#unit-testing-your-models">unit tests</a> and test model validations, scopes, callbacks, associations and complex methods to be sure the model is behaving as it should. We write <a href="http://guides.rubyonrails.org/testing.html#functional-tests-for-your-controllers">functional tests</a> to check controller actions, filters, redirects, view rendering, and the like.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-230"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-228">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-229'
	>
	Functional tests also help us to approximately check for errors in our view files. If we have an error inside a view file, the controller test using that view file will fail while rendering it, and we’ll easily find the source of the error.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-233"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-231">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-232'
	>
	We use several gems to help us in writing the tests:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-236"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-234">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-235'
	>
	<li><a href="https://github.com/thoughtbot/factory_girl">FactoryGirl</a> – we use it for quick building and creating instances of objects</li><li><a href="https://github.com/thoughtbot/shoulda">Shoulda</a> – great helpers which speed up writing simple and iterative tests, for example, testing model validations</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-239"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-237">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-238'
	>
	Testing JavaScript</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-242"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-240">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-241'
	>
	Some applications have a lot of code in JavaScript, so we started with some basic JavaScript testing for Rails applications. Here we’re using:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-245"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-243">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-244'
	>
	<li>Jasmine – a <a href="http://en.wikipedia.org/wiki/Behavior-driven_development">BDD</a> testing framework</li><li>jasmine-rails – a gem which helps us integrate Jasmine into the standard Ruby on Rails testing workflow.</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-248"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-246">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-247'
	>
	By using jasmine-rails, we’re able to run the JavaScript specs either in the browser or from the command line. The latter is important for us because it enables us to automate this task.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-251"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-249">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-250'
	>
	Automation by Semaphore</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-254"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-252">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-253'
	>
	When we have a good test suite, we want to further automate our workflow. You can go two ways here – set up and maintain your own CI server or go with a hosted one and just pay someone else to do it for you.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-257"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-255">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-256'
	>
	We went with a great hosted CI solution called <a href="https://semaphoreapp.com/">Semaphore</a>. Semaphore connects to your <a href="https://github.com">Github</a> repositories and receives an automatic trigger for every code commit. From there it runs standard build tasks like bundle install, rake db:migrate, rake test, etc. All these tasks can be modified to suite the needs of the project.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-260"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-258"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-259">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/02/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat-2.webp"
					class="image__img block-media__image-img"
					alt=""
										height="992"
															width="772"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-263"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-261">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-262'
	>
	If the build fails, notifications get sent out to team members, who can easily track the problem in the build log. This way, our team doesn’t need to waste time on running all the tests locally. They simply commit the code and get notified only if something goes wrong.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-266"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-264">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-265'
	>
	If all tasks run successfully, it can also do <a href="https://infinum.com/blog/faster-web-application-deployments-using-mina-instead-of-capistrano/">automatic deployment</a> to a server you define. We usually have two servers for every project:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-269"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-267">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-268'
	>
	<li><strong>production</strong> – the main server and the one used by users</li><li><strong>staging</strong> – where we test out features before releasing them to the general population</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-272"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-270">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-271'
	>
	When we’re developing new features, we usually do them in feature branches so we don’t mess with the master branch. The master branch needs to always be “deployable”. When we create a new branch, it gets automatically added to Semaphore.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-275"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-273">
	<h3	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-274'
	>
	Polishing with CodeClimate</h3></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-278"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-276">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-277'
	>
	We use one more tool in our workflow. It’s not a standard CI tool, but a tool for <strong>automated code reviewing</strong>, called <a href="https://codeclimate.com/">CodeClimate</a>. It also gets triggered on every code commit and runs a series of code quality checks and security analyses like:</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-281"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="lists" data-id="es-279">
	<ul	class='typography typography--size-16-text-roman js-typography lists__typography'
	data-id='es-280'
	>
	<li>test coverage</li><li>code complexity</li><li>code smells</li><li>security issues</li><li>potential vulnerabilities</li></ul></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-284"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-282"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-283">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/02/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat-3.webp"
					class="image__img block-media__image-img"
					alt=""
										height="832"
															width="1283"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-287"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-285">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-286'
	>
	With CodeClimate, our team gets notified about new issues and <strong>changes in code quality in real time</strong>. This increases the team’s awareness of the state of the code and improves overall maintainability in the long run.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-290"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-288">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-289'
	>
	We’ve also integrated CodeClimate with HipChat so we receive notifications directly to HipChat rooms. Since we use Hipchat as our primary communication tool, the fact that Semaphore and CodeClimate are both integrated with it comes in really handy.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-293"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-media">
	<div	class="media block-media__media media__border--none media__align--center-center"
	data-id="es-291"
	 data-media-type='image'>

	<figure class="image block-media__image-figure image--size-stretch" data-id="es-292">
	<picture class="image__picture block-media__image-picture">
												<img
					src="https://infinum.com/uploads/2014/01/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat-4.webp"
					class="image__img block-media__image-img"
					alt=""
										height="159"
															width="997"
										loading="lazy"
					 />
					</picture>

	</figure></div></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-296"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-294">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-295'
	>
	You see, when you’re developing a complex application, chances are you start getting sloppy. You cut corners, introduce hacks and, in general, stop paying attention to code quality. CodeClimate keeps us in check and stops us from incurring too much <a href="http://martinfowler.com/bliki/TechnicalDebt.html">technical debt</a>.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-299"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-heading" data-id="es-297">
	<h2	class='typography typography--size-36-text js-typography block-heading__heading'
	data-id='es-298'
	>
	A work in progress</h2></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-302"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-300">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-301'
	>
	With the combination of different tools and techniques mentioned before, we’ve managed to automate our workflow and drastically reduce the time we spend on testing, building, deploying and debugging our applications. As always, there is still room for improvement, but we are proud of what we’ve managed to achieve so far.</p></div>	</div>

<div
	class="wrapper wrapper__use-simple--true"
	data-id="es-305"
	 data-animation='slideFade' data-animation-target='inner-items'>
		
			<div class="block-paragraph" data-id="es-303">
	<p	class='typography typography--size-16-text-roman js-typography block-paragraph__paragraph'
	data-id='es-304'
	>
	Please note that it’s very important to have a dedicated Continuous Integration server. The reason for that is simple – the <strong>nag factor</strong>! The CI server, especially if it is integrated with HipChat or a similar communication tool, constantly nags developers to solve the issues that show up with their code. This way, problems get solved as they are introduced – every hour, every day – which is exactly the point of Continuous Integration.</p></div>	</div>
</div>
</div>		</div>
	</div><p>The post <a href="https://infinum.com/blog/a-ruby-on-rails-continous-integration-process-using-semaphore-github-codeclimate-and-hipchat/">A Ruby on Rails Continuous Integration Process Using Github, Semaphore, CodeClimate and HipChat</a> appeared first on <a href="https://infinum.com">Infinum</a>.</p>
]]>
				</content:encoded>
			</item>
		
	</channel>
</rss>