From 67de73f67ea4f7afeb68829fb510065ed8d41159 Mon Sep 17 00:00:00 2001 From: a14m Date: Mon, 14 Dec 2020 14:17:39 +0100 Subject: Add codecov integration --- CLI/ruby/.rubocop.yml | 1 + CLI/ruby/Gemfile.lock | 13 +++++++++++++ CLI/ruby/game_of_life.gemspec | 3 +++ CLI/ruby/spec/spec_helper.rb | 6 ++++++ 4 files changed, 23 insertions(+) (limited to 'CLI/ruby') diff --git a/CLI/ruby/.rubocop.yml b/CLI/ruby/.rubocop.yml index 970b547..075df4f 100644 --- a/CLI/ruby/.rubocop.yml +++ b/CLI/ruby/.rubocop.yml @@ -10,6 +10,7 @@ Layout/LineLength: Metrics/BlockLength: Exclude: + - "game_of_life.gemspec" - "spec/**/*" Naming/MethodParameterName: diff --git a/CLI/ruby/Gemfile.lock b/CLI/ruby/Gemfile.lock index 002d5c4..c3ad0ed 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) @@ -51,6 +56,12 @@ GEM rubocop-ast (1.2.0) parser (>= 2.7.1.5) 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 +71,13 @@ PLATFORMS DEPENDENCIES bundler + codecov pry-byebug rake redcarpet rspec rubocop + simplecov terminal_game_of_life! yard diff --git a/CLI/ruby/game_of_life.gemspec b/CLI/ruby/game_of_life.gemspec index 9f88e68..940efdf 100644 --- a/CLI/ruby/game_of_life.gemspec +++ b/CLI/ruby/game_of_life.gemspec @@ -31,6 +31,9 @@ Gem::Specification.new do |spec| spec.add_development_dependency "rake" spec.add_development_dependency "rspec" spec.add_development_dependency "rubocop" + # 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/spec_helper.rb b/CLI/ruby/spec/spec_helper.rb index 890ca34..0c453de 100644 --- a/CLI/ruby/spec/spec_helper.rb +++ b/CLI/ruby/spec/spec_helper.rb @@ -1,5 +1,11 @@ # frozen_string_literal: true +require "simplecov" +SimpleCov.start + +require "codecov" +SimpleCov.formatter = SimpleCov::Formatter::Codecov if ENV["CODECOV_TOKEN"] + require "bundler/setup" require "game_of_life" -- cgit v1.2.3 From 3a84b11208e8378424790be4302a82f61a556186 Mon Sep 17 00:00:00 2001 From: a14m Date: Mon, 14 Dec 2020 15:13:18 +0100 Subject: Add rubocop-rspec --- CLI/ruby/Gemfile.lock | 4 ++++ CLI/ruby/game_of_life.gemspec | 1 + 2 files changed, 5 insertions(+) (limited to 'CLI/ruby') diff --git a/CLI/ruby/Gemfile.lock b/CLI/ruby/Gemfile.lock index c3ad0ed..1cd8a09 100644 --- a/CLI/ruby/Gemfile.lock +++ b/CLI/ruby/Gemfile.lock @@ -55,6 +55,9 @@ 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) @@ -77,6 +80,7 @@ DEPENDENCIES 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 940efdf..b59ea88 100644 --- a/CLI/ruby/game_of_life.gemspec +++ b/CLI/ruby/game_of_life.gemspec @@ -31,6 +31,7 @@ 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" -- cgit v1.2.3 From e706a28b85b47d9c6944cff691b88101c1605138 Mon Sep 17 00:00:00 2001 From: a14m Date: Mon, 14 Dec 2020 15:13:37 +0100 Subject: Fix rspec violations and complete coverage testing --- CLI/ruby/.rubocop.yml | 11 ++++++ CLI/ruby/spec/game_of_life/cell_spec.rb | 31 ++++++++++------ CLI/ruby/spec/game_of_life/plane_spec.rb | 20 +++++----- CLI/ruby/spec/game_of_life_spec.rb | 63 +++++++++++++++++++++++--------- 4 files changed, 86 insertions(+), 39 deletions(-) (limited to 'CLI/ruby') diff --git a/CLI/ruby/.rubocop.yml b/CLI/ruby/.rubocop.yml index 075df4f..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 @@ -47,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/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..285b766 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("") + 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,18 @@ RSpec.describe GameOfLife do end end - describe.pending ".render" + describe ".render" do + let(:universe) { GameOfLife::Universe.new(width: 3, height: 3) } + + 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 + end end -- cgit v1.2.3 From e674394831d64aa5f64b9ca2b6a67ca16704e358 Mon Sep 17 00:00:00 2001 From: a14m Date: Mon, 14 Dec 2020 15:18:33 +0100 Subject: Ignore rubocop violation about any instance --- CLI/ruby/spec/game_of_life_spec.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'CLI/ruby') diff --git a/CLI/ruby/spec/game_of_life_spec.rb b/CLI/ruby/spec/game_of_life_spec.rb index 285b766..5e99ca8 100644 --- a/CLI/ruby/spec/game_of_life_spec.rb +++ b/CLI/ruby/spec/game_of_life_spec.rb @@ -151,6 +151,7 @@ RSpec.describe GameOfLife do 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) @@ -161,5 +162,6 @@ RSpec.describe GameOfLife do described_class.render(universe) end + # rubocop:enable RSpec/AnyInstance end end -- cgit v1.2.3 From b710263617e019e4ffed3dbafcc6795f760bb151 Mon Sep 17 00:00:00 2001 From: a14m Date: Mon, 14 Dec 2020 20:07:09 +0100 Subject: Add codecov configurations for monorepo --- CLI/ruby/.gitlab-ci.yml | 7 +------ CLI/ruby/CHANGELOG.md | 1 + CLI/ruby/spec/spec_helper.rb | 5 ++++- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'CLI/ruby') 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/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/spec/spec_helper.rb b/CLI/ruby/spec/spec_helper.rb index 0c453de..e7feb44 100644 --- a/CLI/ruby/spec/spec_helper.rb +++ b/CLI/ruby/spec/spec_helper.rb @@ -1,7 +1,10 @@ # frozen_string_literal: true require "simplecov" -SimpleCov.start +SimpleCov.start do + add_filter "/spec/" + enable_coverage :branch +end require "codecov" SimpleCov.formatter = SimpleCov::Formatter::Codecov if ENV["CODECOV_TOKEN"] -- cgit v1.2.3