The ability of having immediate feedback on what we are working should be one of the most important characteristics in software development. Imagine making one change to our source code and having to wait 2 weeks to see if it broke something? oh! That would be a nightmare! For this, Continuous Integration will help a team to have immediate and frequent feedback about the status of what they are building.
Martin Fowler defines Continuous Integration as a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily - leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly.
These tools not only will let us build and test our code each time the source has changed but also deploy the result (if the build was successful) or use automatic builds, and maybe test against different platforms, to mention a few.
The example application
Note that we won't be using TDD in the example itself, but we will mimic as if the example code is the result of the first iterations.
Another important thing to mention is that we are using
crystal init to create the application.
And here's the implementation:
# src/game_of_life.cr class Location getter x : Int32 getter y : Int32 def self.random Location.new(Random.rand(10), Random.rand(10)) end def initialize(@x, @y) end end class World @living_cells : Array(Location) def self.empty new end def initialize(living_cells =  of Location) @living_cells = living_cells end def set_living_at(a_location) @living_cells << a_location end def is_empty? @living_cells.size == 0 end end
And the specs:
# spec/game_of_life_spec.cr require "./spec_helper" describe "a new world" do it "should be empty" do world = World.new world.is_empty?.should be_true end end describe "an empty world" do it "should not be empty after adding a cell" do world = World.empty world.set_living_at(Location.random) world.is_empty?.should be_false end end
And this is all we need for our continuous integration examples! Let's start!
Continuous Integration step by step
Here's the list of items we want to achieve:
- Build and run specs using 3 different Crystal's versions:
- 0.31.1 (using a Docker image)
- Install shards packages
- Install binary dependencies
- Use a database (for example MySQL)
- Cache dependencies to make the build run faster
From here choose your next steps: