From 911acef526cbfb7d079810173b9a91fc1e9da6a2 Mon Sep 17 00:00:00 2001 From: Sam Phippen Date: Sun, 19 Jun 2016 13:02:15 +0100 Subject: [PATCH] Add an initial setup for RSpec examples. Adds: * Makefile commands for: * Seeding each exercise with a common RSpec setup * Running RSpec for each exercise * Running RSpec for all exercises * An example implementation of what the RSpec solution would look like for the "wordy" exercise. Also: ignores only the root `Gemfile.lock`. We need `exercises/**/Gemfile.lock` to exist so that the version of RSpec that exists in each one is pinned. I've chosen here to do a somewhat literal translation of the minitest exercises into RSpec. That is that there is no usage of subject, let, before, nested contexts etc. The reason for that is that it feels to me like exercism exercises are mostly done by beginners learning to do TDD and so slamming them with extra RSpec concepts is unwise. Also, at least for this problem, it doesn't feel like we're proving out boolean cases so much as we are adding one test at a time to force complexity. One RSpec feature I've taken advantage of that isn't used in minitest is providing a docstring to skip, basically making it extremely explicit in which order the examples should be satisfied. I feel like exercism users are used to going from the top down anyway, but I figured the extra degree of inline docs is useful. What do people think? In terms of spec naming style I've gone with the authoritative "it can/it can't" do things. One other style that could be used here is the "it adds two numbers together", "it multiplies and then adds numbers". I personally think that gets harder to read as we add more cases, but I'd love to hear feedback on that. Regarding documentation: I'm aware that at the moment the documentation reflects the fact that minitest is built in to ruby, and so most people can just immediately get started. One open question is what are all the places we need to document how to work with RSpec? If we decide we like this approach, I'm happy to go ahead. I'd love to get feedback on copy and style choices before I plough ahead with adding specs to all the examples though. Thanks ^_^ --- .gitignore | 2 +- Makefile | 13 ++++ bin/rspec-test-in | 4 + exercises/wordy/.rspec | 3 + exercises/wordy/Gemfile | 6 ++ exercises/wordy/Gemfile.lock | 26 +++++++ exercises/wordy/wordy_spec.rb | 136 ++++++++++++++++++++++++++++++++++ lib/disable_rspec_skip.rb | 4 + 8 files changed, 193 insertions(+), 1 deletion(-) create mode 100755 bin/rspec-test-in create mode 100644 exercises/wordy/.rspec create mode 100644 exercises/wordy/Gemfile create mode 100644 exercises/wordy/Gemfile.lock create mode 100644 exercises/wordy/wordy_spec.rb create mode 100644 lib/disable_rspec_skip.rb diff --git a/.gitignore b/.gitignore index 8f9a68db9d..e267dad887 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ .bundle bin/configlet bin/configlet.exe -Gemfile.lock +/Gemfile.lock diff --git a/Makefile b/Makefile index 5ebeac1198..6d10a7112b 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ FILEEXT := "rb" EXAMPLE := "example.$(FILEEXT)" SRCFILE := "$(shell echo $(ASSIGNMENT) | sed 's/-/_/g')" TSTFILE := "$(SRCFILE)_test.$(FILEEXT)" +SPECFILE := "$(SRCFILE)_spec.$(FILEEXT)" # Any additional arguments, such as -p for pretty output and others ARGS ?= "" @@ -22,10 +23,13 @@ test-assignment: @echo "" @echo "" @echo "----------------------------------------------------------------" + @pwd @echo "running tests for: $(ASSIGNMENT)" @cp -r ./exercises/$(ASSIGNMENT)/* $(OUTDIR) + @cp -r ./exercises/$(ASSIGNMENT)/.rspec $(OUTDIR)/.rspec @cp ./exercises/$(ASSIGNMENT)/$(EXAMPLE) $(OUTDIR)/$(SRCFILE).$(FILEEXT) @ruby -I./lib -rdisable_skip.rb $(OUTDIR)/$(TSTFILE) $(ARGS) + @./bin/rspec-test-in $(OUTDIR) @rm -rf $(OUTDIR) # all tests @@ -34,3 +38,12 @@ test: ASSIGNMENT=$$assignment $(MAKE) -s test-assignment || exit 1;\ done +seed_rspec: + @for assignment in $(ASSIGNMENTS); do \ + ASSIGNMENT=$$assignment $(MAKE) -s seed_individual_assignment_with_rspec || exit 1;\ + done + +seed_individual_assignment_with_rspec: + @cd ./exercises/$(ASSIGNMENT) && bundle init && echo 'gem "rspec", "~> 3.4.0"' >> Gemfile || exit 0 + @cd ./exercises/$(ASSIGNMENT) && bundle install + @cd ./exercises/$(ASSIGNMENT) && echo '--color\n--order=random\n--pattern *_spec.rb' > .rspec diff --git a/bin/rspec-test-in b/bin/rspec-test-in new file mode 100755 index 0000000000..492ae35f9d --- /dev/null +++ b/bin/rspec-test-in @@ -0,0 +1,4 @@ +#!/bin/bash + +CWD=`pwd` +cd $1 && bundle install && bundle exec rspec -r $CWD/lib/disable_rspec_skip.rb diff --git a/exercises/wordy/.rspec b/exercises/wordy/.rspec new file mode 100644 index 0000000000..52c966c9f5 --- /dev/null +++ b/exercises/wordy/.rspec @@ -0,0 +1,3 @@ +--color +--order=random +--pattern *_spec.rb diff --git a/exercises/wordy/Gemfile b/exercises/wordy/Gemfile new file mode 100644 index 0000000000..b601e73a5d --- /dev/null +++ b/exercises/wordy/Gemfile @@ -0,0 +1,6 @@ +# frozen_string_literal: true +# A sample Gemfile +source "https://rubygems.org" + +# gem "rails" +gem "rspec", "~> 3.4.0" diff --git a/exercises/wordy/Gemfile.lock b/exercises/wordy/Gemfile.lock new file mode 100644 index 0000000000..6170d487c2 --- /dev/null +++ b/exercises/wordy/Gemfile.lock @@ -0,0 +1,26 @@ +GEM + remote: https://rubygems.org/ + specs: + diff-lcs (1.2.5) + rspec (3.4.0) + rspec-core (~> 3.4.0) + rspec-expectations (~> 3.4.0) + rspec-mocks (~> 3.4.0) + rspec-core (3.4.4) + rspec-support (~> 3.4.0) + rspec-expectations (3.4.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.4.0) + rspec-mocks (3.4.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.4.0) + rspec-support (3.4.1) + +PLATFORMS + ruby + +DEPENDENCIES + rspec (~> 3.4.0) + +BUNDLED WITH + 1.12.5 diff --git a/exercises/wordy/wordy_spec.rb b/exercises/wordy/wordy_spec.rb new file mode 100644 index 0000000000..99983a8191 --- /dev/null +++ b/exercises/wordy/wordy_spec.rb @@ -0,0 +1,136 @@ +require_relative "./wordy" + +RSpec.describe WordProblem do + it "can add one to one" do + problem = WordProblem.new("What is 1 plus 1?") + + expect(problem.answer).to eq(2) + end + + it "can add two to fifty three" do + skip "fix this test second - delete the `skip` lines to enable individual tests" + + problem = WordProblem.new('What is 53 plus 2?') + + expect(problem.answer).to eq(55) + end + + it "can add negative numbers together" do + skip "fix this test third" + + problem = WordProblem.new('What is -1 plus -10?') + + expect(problem.answer).to eq(-11) + end + + it "can add larger numbers together" do + skip "fix this test fourth" + + problem = WordProblem.new('What is 123 plus 45678?') + + expect(problem.answer).to eq(45_801) + end + + it "can subtract numbers from each other" do + skip "fix this test fifth" + + problem = WordProblem.new('What is 4 minus -12?') + + expect(problem.answer).to eq(16) + end + + it "can multiply numbers together" do + skip "fix this test sixth" + + problem = WordProblem.new('What is -3 multiplied by 25?') + + expect(problem.answer).to eq(-75) + end + + it "can divide two numbers" do + skip "fix this test seventh" + + problem = WordProblem.new('What is 33 divided by -3?') + + expect(problem.answer).to eq(-11) + end + + it "can add numbers together multiple times" do + skip "fix this test eight" + + question = 'What is 1 plus 1 plus 1?' + problem = WordProblem.new(question) + + expect(problem.answer).to eq(3) + end + + it "can add and then subtract a number" do + skip "fix this test ninth" + + question = 'What is 1 plus 5 minus -2?' + problem = WordProblem.new(question) + + expect(problem.answer).to eq(8) + end + + it "can subtract numbers twice" do + skip "fix this test tenth" + + question = 'What is 20 minus 4 minus 13?' + problem = WordProblem.new(question) + + expect(problem.answer).to eq(3) + end + + it "can subtract then add a number" do + skip "fix this test eleventh" + + question = 'What is 17 minus 6 plus 3?' + problem = WordProblem.new(question) + + expect(problem.answer).to eq(14) + end + + it "can multiply numbers twice" do + skip "fix this test twelth" + + question = 'What is 2 multiplied by -2 multiplied by 3?' + problem = WordProblem.new(question) + + expect(problem.answer).to eq(-12) + end + + it "can add then multiply numbers" do + skip "fix this test thirtheenth" + + question = 'What is -3 plus 7 multiplied by -2?' + problem = WordProblem.new(question) + + expect(problem.answer).to eq(-8) + end + + it "can divide numbers twice" do + skip "fix this test fourteenth" + + question = 'What is -12 divided by 2 divided by -3?' + problem = WordProblem.new(question) + + expect(problem.answer).to eq(2) + end + + it "can't do advanced math" do + skip "fix this test fifteenth" + + problem = WordProblem.new('What is 53 cubed?') + + expect { problem.answer }.to raise_error(ArgumentError) + end + + it "can't answer irrelevant questions" do + skip "fix this test sixteenth" + + problem = WordProblem.new('Who is the president of the United States?') + + expect { problem.answer }.to raise_error(ArgumentError) + end +end diff --git a/lib/disable_rspec_skip.rb b/lib/disable_rspec_skip.rb new file mode 100644 index 0000000000..e2b04f9888 --- /dev/null +++ b/lib/disable_rspec_skip.rb @@ -0,0 +1,4 @@ +RSpec::Core::Pending.class_eval do + def skip(*args) + end +end