diff options
| author | a14m <[email protected]> | 2020-12-14 22:03:57 +0000 |
|---|---|---|
| committer | a14m <[email protected]> | 2020-12-14 22:03:57 +0000 |
| commit | 50a9f841d6b27a0c842bf5127940d4989a621d10 (patch) | |
| tree | 0eef3a3f5618a0e7e71164e74db1e49d187fdd92 /CLI/ruby | |
| parent | 628e5e81596892cadfd5b5dea46001556b6a7d49 (diff) | |
| parent | b710263617e019e4ffed3dbafcc6795f760bb151 (diff) | |
Merge branch 'feature/code-coverage' into 'master'
Feature/code coverage
See merge request a14m/game-of-life!10
Diffstat (limited to 'CLI/ruby')
| -rw-r--r-- | CLI/ruby/.gitlab-ci.yml | 7 | ||||
| -rw-r--r-- | CLI/ruby/.rubocop.yml | 12 | ||||
| -rw-r--r-- | CLI/ruby/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | CLI/ruby/Gemfile.lock | 17 | ||||
| -rw-r--r-- | CLI/ruby/game_of_life.gemspec | 4 | ||||
| -rw-r--r-- | CLI/ruby/spec/game_of_life/cell_spec.rb | 31 | ||||
| -rw-r--r-- | CLI/ruby/spec/game_of_life/plane_spec.rb | 20 | ||||
| -rw-r--r-- | CLI/ruby/spec/game_of_life_spec.rb | 65 | ||||
| -rw-r--r-- | CLI/ruby/spec/spec_helper.rb | 9 |
9 files changed, 121 insertions, 45 deletions
diff --git a/CLI/ruby/.gitlab-ci.yml b/CLI/ruby/.gitlab-ci.yml index d573ce5..6fdf07e 100644 --- a/CLI/ruby/.gitlab-ci.yml +++ b/CLI/ruby/.gitlab-ci.yml @@ -1,9 +1,4 @@ image: ruby:2.7 -stages: - - build - - test - - lint - - release variables: BUNDLE_PATH: .bundle/vendor @@ -58,7 +53,7 @@ lint: - bundle exec rubocop release: - stage: release + stage: deploy needs: ["test:2.7", "test:2.6", "test:2.5", lint] rules: - if: $CI_COMMIT_TAG =~ /^ruby\/v.*$/ diff --git a/CLI/ruby/.rubocop.yml b/CLI/ruby/.rubocop.yml index 970b547..a84ca99 100644 --- a/CLI/ruby/.rubocop.yml +++ b/CLI/ruby/.rubocop.yml @@ -1,3 +1,6 @@ +require: + - rubocop-rspec + AllCops: TargetRubyVersion: 2.5 NewCops: enable @@ -10,6 +13,7 @@ Layout/LineLength: Metrics/BlockLength: Exclude: + - "game_of_life.gemspec" - "spec/**/*" Naming/MethodParameterName: @@ -46,3 +50,11 @@ Style/TrailingCommaInArrayLiteral: Style/TrailingCommaInHashLiteral: EnforcedStyleForMultiline: comma +RSpec/ExampleLength: + Max: 12 + +RSpec/MessageSpies: + EnforcedStyle: receive + +RSpec/MultipleExpectations: + Max: 4 diff --git a/CLI/ruby/CHANGELOG.md b/CLI/ruby/CHANGELOG.md index 48aad2a..3f6f77d 100644 --- a/CLI/ruby/CHANGELOG.md +++ b/CLI/ruby/CHANGELOG.md @@ -6,6 +6,7 @@ - Fix `game-of-life --delay -10` error with kernel sleep - Fix `game-of-life --width -10` error with generated universe width - Fix `game-of-life --height -10` error with generated universe height +- Add coverage report ## 1.0.0 - Add ruby testing matrix for versions 2.5, 2.6 and 2.7 diff --git a/CLI/ruby/Gemfile.lock b/CLI/ruby/Gemfile.lock index 002d5c4..1cd8a09 100644 --- a/CLI/ruby/Gemfile.lock +++ b/CLI/ruby/Gemfile.lock @@ -9,8 +9,13 @@ GEM specs: ast (2.4.1) byebug (11.1.3) + codecov (0.2.12) + json + simplecov coderay (1.1.3) diff-lcs (1.4.4) + docile (1.3.2) + json (2.3.1) method_source (1.0.0) parallel (1.20.1) parser (2.7.2.0) @@ -50,7 +55,16 @@ GEM unicode-display_width (>= 1.4.0, < 2.0) rubocop-ast (1.2.0) parser (>= 2.7.1.5) + rubocop-rspec (2.0.1) + rubocop (~> 1.0) + rubocop-ast (>= 1.1.0) ruby-progressbar (1.10.1) + simplecov (0.20.0) + docile (~> 1.1) + simplecov-html (~> 0.11) + simplecov_json_formatter (~> 0.1) + simplecov-html (0.12.3) + simplecov_json_formatter (0.1.2) thor (1.0.1) unicode-display_width (1.7.0) yard (0.9.25) @@ -60,11 +74,14 @@ PLATFORMS DEPENDENCIES bundler + codecov pry-byebug rake redcarpet rspec rubocop + rubocop-rspec + simplecov terminal_game_of_life! yard diff --git a/CLI/ruby/game_of_life.gemspec b/CLI/ruby/game_of_life.gemspec index 9f88e68..b59ea88 100644 --- a/CLI/ruby/game_of_life.gemspec +++ b/CLI/ruby/game_of_life.gemspec @@ -31,6 +31,10 @@ Gem::Specification.new do |spec| spec.add_development_dependency "rake" spec.add_development_dependency "rspec" spec.add_development_dependency "rubocop" + spec.add_development_dependency "rubocop-rspec" + # Code Coverage dependencies + spec.add_development_dependency "codecov" + spec.add_development_dependency "simplecov" # Documentation dependencies spec.add_development_dependency "redcarpet" spec.add_development_dependency "yard" diff --git a/CLI/ruby/spec/game_of_life/cell_spec.rb b/CLI/ruby/spec/game_of_life/cell_spec.rb index 00f55b3..088bdae 100644 --- a/CLI/ruby/spec/game_of_life/cell_spec.rb +++ b/CLI/ruby/spec/game_of_life/cell_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +# rubocop:disable RSpec/MultipleSubjects +# rubocop:disable RSpec/EmptyLineAfterSubject RSpec.describe GameOfLife::Cell do subject(:living_cell) { described_class.new(x: nil, y: nil, alive: true) } subject(:dead_cell) { described_class.new(x: nil, y: nil, alive: false) } @@ -20,6 +22,8 @@ RSpec.describe GameOfLife::Cell do end end + # rubocop:disable RSpec/SubjectStub + # rubocop:disable RSpec/StubbedMock describe "#evolve!" do it "calls #living_neighbors with param: neighbors" do neighbors = [1, 2, 3, 4, 5] @@ -29,17 +33,18 @@ RSpec.describe GameOfLife::Cell do context "when dead" do it "stays dead" do - expect(dead_cell).to receive(:living_neighbors).with([]).and_return 0 + allow(dead_cell).to receive(:living_neighbors).with([]).and_return 0 + expect(dead_cell).to receive(:living_neighbors) next_generation = dead_cell.evolve!([]) expect(next_generation.object_id).to eq dead_cell.object_id - expect(next_generation.dead?).to be_truthy + expect(next_generation).to be_dead end it "becomes alive when having 3 living neighbors" do expect(dead_cell).to receive(:living_neighbors).with([]).and_return 3 next_generation = dead_cell.evolve!([]) expect(next_generation.object_id).not_to eq dead_cell.object_id - expect(next_generation.alive?).to be_truthy + expect(next_generation).to be_alive end end @@ -48,40 +53,42 @@ RSpec.describe GameOfLife::Cell do expect(living_cell).to receive(:living_neighbors).with([]).and_return 2 next_generation = living_cell.evolve!([]) expect(next_generation.object_id).to eq living_cell.object_id - expect(next_generation.alive?).to be_truthy + expect(next_generation).to be_alive end it "survives when having 3 neighbors" do expect(living_cell).to receive(:living_neighbors).with([]).and_return 3 next_generation = living_cell.evolve!([]) expect(next_generation.object_id).to eq living_cell.object_id - expect(next_generation.alive?).to be_truthy + expect(next_generation).to be_alive end it "dies when having less than 2 neighbors" do expect(living_cell).to receive(:living_neighbors).with([]).and_return 1 next_generation = living_cell.evolve!([]) expect(next_generation.object_id).not_to eq living_cell.object_id - expect(next_generation.dead?).to be_truthy + expect(next_generation).to be_dead end it "dies when having more than 3 neighbors" do expect(living_cell).to receive(:living_neighbors).with([]).and_return 4 next_generation = living_cell.evolve!([]) expect(next_generation).not_to eq living_cell - expect(next_generation.dead?).to be_truthy + expect(next_generation).to be_dead end end end + # rubocop:enable RSpec/SubjectStub + # rubocop:enable RSpec/StubbedMock describe "#alive?" do - it { expect(living_cell.alive?).to be_truthy } - it { expect(dead_cell.alive?).to be_falsy } + it { expect(living_cell).to be_alive } + it { expect(dead_cell).not_to be_alive } end describe "#dead?" do - it { expect(living_cell.dead?).to be_falsy } - it { expect(dead_cell.dead?).to be_truthy } + it { expect(living_cell).not_to be_dead } + it { expect(dead_cell).to be_dead } end describe "#living_neighbors" do @@ -134,3 +141,5 @@ RSpec.describe GameOfLife::Cell do end end end +# rubocop:enable RSpec/MultipleSubjects +# rubocop:enable RSpec/EmptyLineAfterSubject diff --git a/CLI/ruby/spec/game_of_life/plane_spec.rb b/CLI/ruby/spec/game_of_life/plane_spec.rb index c4efbb4..88ce0dc 100644 --- a/CLI/ruby/spec/game_of_life/plane_spec.rb +++ b/CLI/ruby/spec/game_of_life/plane_spec.rb @@ -3,36 +3,36 @@ RSpec.describe GameOfLife::Plane do describe "#[]" do context "when empty" do - subject { described_class.new } + subject(:cyclic_array) { described_class.new } it "returns nil with [-1]" do - expect(subject[-1]).to be_nil + expect(cyclic_array[-1]).to be_nil end it "returns nil with [0]" do - expect(subject[0]).to be_nil + expect(cyclic_array[0]).to be_nil end it "returns nil with [1]" do - expect(subject[1]).to be_nil + expect(cyclic_array[1]).to be_nil end end context "when not empty" do - subject { described_class.new([0, 1, 2, 3]) } + subject(:cyclic_array) { described_class.new([0, 1, 2, 3]) } it "returns value at index" do - expect(subject[0]).to eq 0 + expect(cyclic_array[0]).to eq 0 end it "returns value at -index (negative indices count backward from the end of the array)" do - expect(subject[-5]).to eq 3 - expect(subject[-1]).to eq 3 + expect(cyclic_array[-5]).to eq 3 + expect(cyclic_array[-1]).to eq 3 end it "returns value at any index (indices bigger than size cycle again from the beginning)" do - expect(subject[5]).to eq 1 - expect(subject[9]).to eq 1 + expect(cyclic_array[5]).to eq 1 + expect(cyclic_array[9]).to eq 1 end end end diff --git a/CLI/ruby/spec/game_of_life_spec.rb b/CLI/ruby/spec/game_of_life_spec.rb index 00b58b8..5e99ca8 100644 --- a/CLI/ruby/spec/game_of_life_spec.rb +++ b/CLI/ruby/spec/game_of_life_spec.rb @@ -2,65 +2,79 @@ RSpec.describe GameOfLife do describe ".parsed_options" do - context "options['delay']" do - it "raises GameOfLife::Error when negative delay" do + before do + console = instance_double("<File:/dev/tty>") + allow(IO).to receive(:console).and_return(console) + allow(console).to receive(:winsize).and_return([10, 20]) + end + + context "with options['delay']" do + it "raises GameOfLife::Error when negative" do options = { "delay" => -13 } expect { described_class.parsed_options(options) }.to raise_error(GameOfLife::Error, /Invalid --delay value/) end - it "uses options['delay'] when provided" do + it "uses options['delay'] when posotive" do options = { "delay" => 15 } expect(described_class.parsed_options(options)).to include("delay" => 15) end end - context "options['width']" do - it "raises GameOfLife::Error when width < 1" do + context "with options['width']" do + it "raises GameOfLife::Error when < 1" do options = { "width" => 0 } expect { described_class.parsed_options(options) }.to raise_error(GameOfLife::Error, /Invalid --width value/) end - it "raises GameOfLife::Error when width > IO.console.winsize[1]" do + it "raises GameOfLife::Error when > IO.console.winsize[1]" do options = { "width" => 23 } - allow(IO).to receive_message_chain(:console, :winsize).and_return([10, 20]) expect { described_class.parsed_options(options) }.to raise_error(GameOfLife::Error, /Invalid --width value/) end - it "uses options['width'] when provided" do + it "uses options['width']" do options = { "width" => 15 } - allow(IO).to receive_message_chain(:console, :winsize).and_return([10, 20]) expect(described_class.parsed_options(options)).to include("width" => 15) end it "uses IO.console.winsize[1] as default" do - allow(IO).to receive_message_chain(:console, :winsize).and_return([10, 20]) expect(described_class.parsed_options({})).to include("width" => 20) end end - context "options['height']" do - it "raises GameOfLife::Error when height < 1" do + context "with options['height']" do + it "raises GameOfLife::Error < 1" do options = { "height" => 0 } expect { described_class.parsed_options(options) }.to raise_error(GameOfLife::Error, /Invalid --height value/) end - it "raises GameOfLife::Error when height > winsize[0] - 2" do + it "raises GameOfLife::Error when > winsize[0] - 2" do options = { "height" => 9 } - allow(IO).to receive_message_chain(:console, :winsize).and_return([10, 20]) expect { described_class.parsed_options(options) }.to raise_error(GameOfLife::Error, /Invalid --height value/) end - it "uses options['height'] when provided" do + it "uses options['height']" do options = { "height" => 5 } - allow(IO).to receive_message_chain(:console, :winsize).and_return([10, 20]) expect(described_class.parsed_options(options)).to include("height" => 5) end it "uses IO.console.winsize[0] - 2 as default" do - allow(IO).to receive_message_chain(:console, :winsize).and_return([10, 20]) expect(described_class.parsed_options({})).to include("height" => 8) end end + + context "with options['seed']" do + it "uses options['seed']" do + options = { "seed" => 1337 } + expect(described_class.parsed_options(options)).to include("seed" => 1337) + end + + # rubocop:disable RSpec/AnyInstance + it "defaults to Kernel.random" do + allow_any_instance_of(Kernel).to receive(:rand).and_return "random" + expect(described_class.parsed_options({})).to include("seed" => "random") + end + # rubocop:enable RSpec/AnyInstance + end end describe ".generate" do @@ -134,5 +148,20 @@ RSpec.describe GameOfLife do end end - describe.pending ".render" + describe ".render" do + let(:universe) { GameOfLife::Universe.new(width: 3, height: 3) } + + # rubocop:disable RSpec/AnyInstance + it "renders the game of life presentation" do + stub_const("BANNER", "") + stub_const("DELAY", 100.0) + expect_any_instance_of(Kernel).to receive(:puts).with("\33c\e[3J") + expect_any_instance_of(Kernel).to receive(:puts).twice + expect(universe).to receive(:to_s) + expect_any_instance_of(Kernel).to receive(:sleep) + + described_class.render(universe) + end + # rubocop:enable RSpec/AnyInstance + end end diff --git a/CLI/ruby/spec/spec_helper.rb b/CLI/ruby/spec/spec_helper.rb index 890ca34..e7feb44 100644 --- a/CLI/ruby/spec/spec_helper.rb +++ b/CLI/ruby/spec/spec_helper.rb @@ -1,5 +1,14 @@ # frozen_string_literal: true +require "simplecov" +SimpleCov.start do + add_filter "/spec/" + enable_coverage :branch +end + +require "codecov" +SimpleCov.formatter = SimpleCov::Formatter::Codecov if ENV["CODECOV_TOKEN"] + require "bundler/setup" require "game_of_life" |
