Решение на Четвърта задача - Unit тестване от Цветан Христов

Обратно към всички решения

Към профила на Цветан Христов

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 16 успешни тест(а)
  • 3 неуспешни тест(а)

Код

RSpec.describe 'Version' do
def version(argument)
version_obj.new(argument)
end
def error_message(string)
"Invalid version string \'#{string}\'"
end
let(:version_obj) { Version }
describe '.new' do
context 'when string is passed' do
it 'raises ArgumentError for invalid input' do
expect { version('1.') }
.to raise_error(ArgumentError, error_message('1.'))
expect { version('.3') }
.to raise_error(ArgumentError, error_message('.3'))
expect { version('0..3') }
.to raise_error(ArgumentError, error_message('0..3'))
expect { version('.3.') }
.to raise_error(ArgumentError, error_message('.3.'))
expect { version('.') }
.to raise_error(ArgumentError, error_message('.'))
expect { version('a.b.c') }
.to raise_error(ArgumentError, error_message('a.b.c'))
expect { version(version('321312..')) }
.to raise_error(ArgumentError, error_message('321312..'))
end
end
context 'when another version is passed' do
it 'raises ArgumentError for invalid input' do
expect { version(version('1.')) }
.to raise_error(ArgumentError, error_message('1.'))
expect { version(version('.3')) }
.to raise_error(ArgumentError, error_message('.3'))
expect { version(version('0..3')) }
.to raise_error(ArgumentError, error_message('0..3'))
expect { version(version('.3.')) }
.to raise_error(ArgumentError, error_message('.3.'))
expect { version(version('.')) }
.to raise_error(ArgumentError, error_message('.'))
end
end
end
describe '#<=>' do
it 'compares using ==' do
expect(version('1.1.0')).to be == version('1.1')
expect(version('1.1')).to be == version('1.1')
expect(version('')).to be == version('0')
expect(version('1')).to be == version('1.0.0.0')
expect(version('0')).to be == version('0.0.0.0')
end
it 'compares using >' do
expect(version('1.2.3')).to be > version('1.2.2')
expect(version('1.2.3')).to be > version('')
expect(version('1.1')).to be > version('1')
expect(version('1.0.1')).to be > version('1.0.0')
end
it 'compares using <' do
expect(version('1.2.3')).to be < version('1.3')
expect(version('1.2.3')).to be < version('1.3.1')
expect(version('1')).to be < version('1.1')
expect(version('1.3.2')).to_not be < version('1.2')
end
it 'compares using >=' do
expect(version('1.3.2')).to be >= version('1.3.2')
expect(version('1.3.2')).to be >= version('1.3')
expect(version('')).to_not be >= version('1')
end
it 'compares using <=' do
expect(version('1')).to be <= version('1')
expect(version('1.2')).to be <= version('1.3')
expect(version('')).to be <= version('0')
end
end
describe '#to_s' do
it 'converts to string' do
expect(version('1.1.0').to_s).to eq('1.1')
expect(version('1.1').to_s).to eq('1.1')
expect(version('').to_s).to eq('')
expect(version('0').to_s).to eq('')
expect(version(version('1.2.3')).to_s).to eq('1.2.3')
end
end
describe '#components' do
context 'when no optional parameter is given' do
it 'breaks into components' do
expect(version('1.3.5').components).to eq [1, 3, 5]
end
it 'excludes zeros at the end' do
expect(version('1.3.5.0').components).to eq [1, 3, 5]
expect(version('1.0.0.0').components).to eq [1]
end
it 'returns empty list for version 0' do
expect(version('').components).to eq []
end
end
context 'when optional parameter is given' do
it 'breaks into N components' do
expect(version('1.3.5').components(1)).to eq [1]
expect(version('1.3.5').components(2)).to eq [1, 3]
expect(version('1.3.5').components(3)).to eq [1, 3, 5]
expect(version('1.3.5.0').components(3)).to eq [1, 3, 5]
expect(version('1.3.5').components(4)).to eq [1, 3, 5, 0]
expect(version('1.3.5').components(0)).to eq [1, 3, 5]
expect(version('').components(4)).to eq [0, 0, 0, 0]
end
end
it 'doesn`t modify the instance' do

Идеята не е да провериш дали components поврежда инстанцията като се викне, а дали components може да се използва, за да се промени инстанцията.

Освен това, object_id-то на инстанцията никога няма да се промени. Каквото и да й правиш.

Промени решението, така че да няма dup, зареди файла в едно irb и се опитай да пресъздадеш проблема. После го направи на тест.

instance = version('1.2.3')
expect { instance.components }.to_not change { instance }
expect { instance.components(1) }.to_not change { instance }
expect { instance.components(2) }.to_not change { instance }
expect { instance.components(3) }.to_not change { instance }
expect { instance.components(4) }.to_not change { instance }
end
end
describe 'Version::Range' do
describe '.new' do
context 'when version is not valid' do
it 'raises ArgumentError' do
argument = '1.0.0.'
expect { Version::Range.new(version(argument), version('2.0.0')) }
.to raise_error(ArgumentError, error_message(argument))
expect { Version::Range.new(version(''), version(argument)) }
.to raise_error(ArgumentError, error_message(argument))
expect { Version::Range.new(argument, '2.0.0') }
.to raise_error(ArgumentError, error_message(argument))
end
end
end
describe '#include?' do
context 'when an instance is passed' do
it 'includes given version' do
range = Version::Range.new(version('1'), version('2'))
expect(range.include?(version('1.5'))).to be true
expect(range.include?(version('1'))).to be true
expect(range.include?(version('1.0.0'))).to be true
expect(range.include?(version('2.1'))).to be false
expect(range.include?(version(''))).to be false
expect(range.include?(version('2'))).to be false
end
end
context 'when a string is passed' do
it 'includes given version' do
first_version = version('1')
second_version = version('2')
range = Version::Range.new(first_version, second_version)
expect(range.include?('1.5')).to be true
expect(range.include?('1')).to be true
expect(range.include?('1')).to be true
expect(range.include?('1.0.0')).to be true
expect(range.include?('2.1')).to be false
expect(range.include?('')).to be false
expect(range.include?('2')).to be false
end
end
end
describe '#to_a' do
context 'when equal versions are passed' do
it 'returns empty list' do
range = Version::Range.new('1.1', '1.1')
expect(range.to_a).to be_empty
end
end
context 'when first version > second version' do
it 'generates all versions between first and second version' do
range = Version::Range.new('1.1.0', '1.1.2')
expect(range.to_a).to eq ['1.1', '1.1.1']
expect(range.to_a).to_not eq ['1.1', '1.1.1', '1.1.2']
expect(range.to_a).to_not eq ['1.1.0', '1.1.1', '1.1.2']
range = Version::Range.new(version('1.1.0'), version('1.2.2'))
expect(range.to_a).to eq [
'1.1', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', '1.1.6', \
'1.1.7', '1.1.8', '1.1.9', '1.2', '1.2.1'
]
range = Version::Range.new('1.1', '1.2')
expect(range.to_a).to eq [
'1.1', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', \
'1.1.6', '1.1.7', '1.1.8', '1.1.9'
]
range = Version::Range.new('', '')
expect(range.to_a).to eq []
end
end
end
end
end

Лог от изпълнението

....F.F...F........

Failures:

  1) spec Version checks that initialize can be given no arguments
     Failure/Error: expect(@solution).to_not pass_tests
       expected this solution to not pass the tests:
       
         class Version
           VALID_VERSION_REGEXP = /\A\z|\A[0-9]+(\.[0-9]+)*\z/
         
           include Comparable
         
           def initialize(version)
             unless VALID_VERSION_REGEXP.match(version.to_s)
               raise ArgumentError, "Invalid version string '#{version}'"
             end
           
             @components = version.to_s
               .split('.')
               .map(&:to_i)
               .reverse
               .drop_while(&:zero?)
               .reverse
           end
         
           def <=>(other)
             @components <=> Version.new(other).internal_components
           end
         
           def internal_components(positions = 0)
             padding_size = positions - @components.size
         
             if padding_size > 0
               @components + [0] * padding_size
             elsif positions != 0
               @components.take(positions)
             else
               @components.dup
             end
           end
         
           def components(positions = 0)
             padding_size = positions - @components.size
         
             if padding_size > 0
               @components + [0] * padding_size
             elsif positions != 0
               @components.take(positions)
             else
               @components.dup
             end
           end
         
           def to_s
             @components.join('.')
           end
         
           class Range
             include Enumerable
         
             def initialize(start_version, end_version)
               @start_version = Version.new(start_version)
               @end_version   = Version.new(end_version)
             end
         
             def include?(version)
               (@start_version <=> version) < 1 && (@end_version <=> version) == 1
             end
         
             def each
               current_version = @start_version
         
               while (current_version <=> @end_version) == -1
                 yield current_version
         
                 current_version = increment_version(current_version)
               end
             end
         
             private
         
             def increment_version(version)
               components = version.internal_components(3)
         
               components[2] += 1
         
               components.to_enum.with_index.reverse_each do |_, index|
                 component = components[index]
         
                 if component >= 10 && components[index - 1]
                   components[index]      = 0
                   components[index - 1] += 1
                 end
               end
         
               Version.new(components.join('.'))
             end
           end
         end
     # /tmp/d20161119-19072-djb2dr/spec.rb:314:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

  2) spec Version checks for comparison operators negatively
     Failure/Error: expect(@solution).to_not pass_tests
       expected this solution to not pass the tests:
       
         class Version
         def >(other)
           true
         end
           VALID_VERSION_REGEXP = /\A\z|\A[0-9]+(\.[0-9]+)*\z/
         
           include Comparable
         
           def initialize(version = '')
             unless VALID_VERSION_REGEXP.match(version.to_s)
               raise ArgumentError, "Invalid version string '#{version}'"
             end
         
             @components = version.to_s
               .split('.')
               .map(&:to_i)
               .reverse
               .drop_while(&:zero?)
               .reverse
           end
         
           def <=>(other)
             @components <=> Version.new(other).internal_components
           end
         
           def internal_components(positions = 0)
             padding_size = positions - @components.size
         
             if padding_size > 0
               @components + [0] * padding_size
             elsif positions != 0
               @components.take(positions)
             else
               @components.dup
             end
           end
         
           def components(positions = 0)
             padding_size = positions - @components.size
         
             if padding_size > 0
               @components + [0] * padding_size
             elsif positions != 0
               @components.take(positions)
             else
               @components.dup
             end
           end
         
           def to_s
             @components.join('.')
           end
         
           class Range
             include Enumerable
         
             def initialize(start_version, end_version)
               @start_version = Version.new(start_version)
               @end_version   = Version.new(end_version)
             end
         
             def include?(version)
               (@start_version <=> version) < 1 && (@end_version <=> version) == 1
             end
         
             def each
               current_version = @start_version
         
               while (current_version <=> @end_version) == -1
                 yield current_version
         
                 current_version = increment_version(current_version)
               end
             end
         
             private
         
             def increment_version(version)
               components = version.internal_components(3)
         
               components[2] += 1
         
               components.to_enum.with_index.reverse_each do |_, index|
                 component = components[index]
         
                 if component >= 10 && components[index - 1]
                   components[index]      = 0
                   components[index - 1] += 1
                 end
               end
         
               Version.new(components.join('.'))
             end
           end
         end
     # /tmp/d20161119-19072-djb2dr/spec.rb:359:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

  3) spec Version tests that #components cannot be used to modify the version
     Failure/Error: expect(@solution).to_not pass_tests
       expected this solution to not pass the tests:
       
         class Version
           VALID_VERSION_REGEXP = /\A\z|\A[0-9]+(\.[0-9]+)*\z/
         
           include Comparable
         
           def initialize(version = '')
             unless VALID_VERSION_REGEXP.match(version.to_s)
               raise ArgumentError, "Invalid version string '#{version}'"
             end
         
             @components = version.to_s
               .split('.')
               .map(&:to_i)
               .reverse
               .drop_while(&:zero?)
               .reverse
           end
         
           def <=>(other)
             @components <=> Version.new(other).internal_components
           end
         
           def internal_components(positions = 0)
             padding_size = positions - @components.size
         
             if padding_size > 0
               @components + [0] * padding_size
             elsif positions != 0
               @components.take(positions)
             else
               @components.dup
             end
           end
         
           def components(positions = 0)
             padding_size = positions - @components.size
           
             if padding_size > 0
               @components + [0] * padding_size
             elsif positions != 0
               @components.take(positions)
             else
               @components
             end
           end
         
           def to_s
             @components.join('.')
           end
         
           class Range
             include Enumerable
         
             def initialize(start_version, end_version)
               @start_version = Version.new(start_version)
               @end_version   = Version.new(end_version)
             end
         
             def include?(version)
               (@start_version <=> version) < 1 && (@end_version <=> version) == 1
             end
         
             def each
               current_version = @start_version
         
               while (current_version <=> @end_version) == -1
                 yield current_version
         
                 current_version = increment_version(current_version)
               end
             end
         
             private
         
             def increment_version(version)
               components = version.internal_components(3)
         
               components[2] += 1
         
               components.to_enum.with_index.reverse_each do |_, index|
                 component = components[index]
         
                 if component >= 10 && components[index - 1]
                   components[index]      = 0
                   components[index - 1] += 1
                 end
               end
         
               Version.new(components.join('.'))
             end
           end
         end
     # /tmp/d20161119-19072-djb2dr/spec.rb:456:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:7:in `block (2 levels) in <top (required)>'

Finished in 17.61 seconds
19 examples, 3 failures

Failed examples:

rspec /tmp/d20161119-19072-djb2dr/spec.rb:298 # spec Version checks that initialize can be given no arguments
rspec /tmp/d20161119-19072-djb2dr/spec.rb:353 # spec Version checks for comparison operators negatively
rspec /tmp/d20161119-19072-djb2dr/spec.rb:441 # spec Version tests that #components cannot be used to modify the version

История (3 версии и 15 коментара)

Цветан обнови решението на 15.11.2016 21:04 (преди почти 2 години)

+RSpec.describe 'Version' do
+ describe '.new' do
+ it 'creates an object with string' do
+ expect( Version.new('1.2.3.4')).to be_instance_of(Version)
+ expect( Version.new('0') ).to be_instance_of(Version)
+ expect( Version.new('') ).to be_instance_of(Version)
+ expect( Version.new ).to be_instance_of(Version)
+ end
+
+ it 'creates an object with instance' do
+ expect( Version.new(Version.new('1.2.3.4')) ).to be_instance_of(Version)
+ expect( Version.new(Version.new('0')) ).to be_instance_of(Version)
+ expect( Version.new(Version.new('')) ).to be_instance_of(Version)
+ expect( Version.new(Version.new) ).to be_instance_of(Version)
+ end
+
+ it 'doesn`t raise error' do
+ expect { Version.new(Version.new('1.2.3')) }.to_not raise_error
+ expect { Version.new('1.2.3') }.to_not raise_error
+ expect { Version.new('1.2.0') }.to_not raise_error
+ expect { Version.new('') }.to_not raise_error
+ expect { Version.new('0') }.to_not raise_error
+ expect { Version.new }.to_not raise_error
+ end
+
+ it 'raises error' do
+ string = '1.'
+ message = "Invalid version string \'#{string}\'"
+ expect { Version.new(string) }.to raise_error(ArgumentError, message)
+ string = '.3'
+ message = "Invalid version string \'#{string}\'"
+ expect { Version.new(string) }.to raise_error(ArgumentError, message)
+ string = '0..3'
+ message = "Invalid version string \'#{string}\'"
+ expect { Version.new(string) }.to raise_error(ArgumentError, message)
+ string = '3,4'
+ message = "Invalid version string \'#{string}\'"
+ expect { Version.new(string) }.to raise_error(ArgumentError, message)
+ string = 'abc'
+ message = "Invalid version string \'#{string}\'"
+ expect { Version.new(string) }.to raise_error(ArgumentError, message)
+ string = 'a.b.c'
+ message = "Invalid version string \'#{string}\'"
+ expect { Version.new(string) }.to raise_error(ArgumentError, message)
+ end
+ end
+
+ describe '#<=>' do
+ it 'compares versions' do
+ expect(Version.new('1.1.0')).to eq(Version.new('1.1'))
+ expect(Version.new('1.1')).to eq(Version.new('1.1'))
+ expect(Version.new('0.1')).not_to eq(Version.new('1'))
+ expect(Version.new('1.2.3')).to be < Version.new('1.3')
+ expect(Version.new('1.2.3')).to be < Version.new('1.3.1')
+ expect(Version.new('')).to eq(Version.new)
+ end
+ end
+
+ describe '#to_s' do
+ it 'converts to string' do
+ expect(Version.new('1.1.0').to_s).to eq('1.1')
+ expect(Version.new('1.1').to_s).to eq('1.1')
+ expect(Version.new('').to_s).to eq('')
+ expect(Version.new.to_s).to eq('')
+ expect(Version.new(Version.new('1.2.3')).to_s).to eq('1.2.3')
+ end
+ end
+
+ describe '#components' do
+ it 'breaks into components' do
+ expect(Version.new('1.3.5').components).to match_array([1, 3, 5])
+ expect(Version.new('1.3.5.0').components).to match_array([1, 3, 5])
+ expect(Version.new('1.0.0.0').components).to match_array([1])
+ expect(Version.new('').components).to match_array([])
+ end
+
+ it 'breaks into N components' do
+ expect(Version.new('1.3.5').components(1)).to match_array([1])
+ expect(Version.new('1.3.5').components(2)).to match_array([1, 3])
+ expect(Version.new('1.3.5').components(3)).to match_array([1, 3, 5])
+ expect(Version.new('1.3.5.0').components(3)).to match_array([1, 3, 5])
+ expect(Version.new('1.3.5').components(4)).to match_array([1, 3, 5, 0])
+ expect(Version.new('1.3.5').components(0)).to match_array([1, 3, 5])
+ expect(Version.new('').components(4)).to match_array([0, 0, 0, 0])
+ end
+ end
+
+ describe 'Version::Range' do
+ describe '.new' do
+ it 'valid input' do
+ expect(Version::Range.new(Version.new('1.0.0'), Version.new('2.0.0')))
+ .to be_instance_of(Version::Range)
+ expect(Version::Range.new('1.0.0', '2.0.0'))
+ .to be_instance_of(Version::Range)
+ end
+
+ it 'invalid input' do
+ message = "Invalid version string \'#{string}\'"
+ expect { Version::Range.new(Version.new(string), Version.new('2.0.0')) }
+ .to raise_error(ArgumentError, message)
+ expect { Version::Range.new(string, '2.0.0') }
+ .to raise_error(ArgumentError, message)
+ end
+ end
+
+ describe '#include?' do
+ it 'includes an instance' do
+ range = Version::Range.new(Version.new('1'), Version.new('2'))
+ expect(range.include?(Version.new('1.5'))).to be true
+ end
+
+ it 'includes a string' do
+ range = Version::Range.new(Version.new('1'), Version.new('2'))
+ expect(range.include?('1.5')).to be true
+ end
+ end
+
+ describe '#to_a' do
+ it 'includes first and exludes last' do
+ range = Version::Range.new(Version.new('1.1.0'), Version.new('1.2.2'))
+ expect(range.to_a).to include('1.1')
+ expect(range.to_a).not_to include('1.2.2')
+ end
+
+ it 'doesn`t list versions for equal ones' do
+ range = Version::Range.new('1.1', '1.1')
+ expect(range.to_a).to eq([])
+ end
+
+ it 'lists all versions' do
+ expect(Version::Range.new('1.1.0', '1.2.2').to_a).to eq \
+ [
+ '1.1', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', \
+ '1.1.6', '1.1.7', '1.1.8', '1.1.9', '1.2', '1.2.1'
+ ]
+ expect(Version::Range.new('1.1', '1.2').to_a).to eq \
+ [
+ '1.1', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', \
+ '1.1.6', '1.1.7', '1.1.8', '1.1.9'
+ ]
+ end
+ end
+ end
+end

Цветан обнови решението на 18.11.2016 00:09 (преди почти 2 години)

RSpec.describe 'Version' do
+ def version(argument)
+ version_obj.new(argument)
+ end
+
+ def error_message(string)
+ "Invalid version string \'#{string}\'"
+ end
+
+ let(:version_obj) { Version }
+
describe '.new' do
- it 'creates an object with string' do
- expect( Version.new('1.2.3.4')).to be_instance_of(Version)
- expect( Version.new('0') ).to be_instance_of(Version)
- expect( Version.new('') ).to be_instance_of(Version)
- expect( Version.new ).to be_instance_of(Version)
+ context 'when string is passed' do
+ it 'raises ArgumentError for invalid input' do
+ expect { version('1.') }
+ .to raise_error(ArgumentError, error_message('1.'))
+ expect { version('.3') }
+ .to raise_error(ArgumentError, error_message('.3'))
+ expect { version('0..3') }
+ .to raise_error(ArgumentError, error_message('0..3'))
+ expect { version('.3.') }
+ .to raise_error(ArgumentError, error_message('.3.'))
+ expect { version('.') }
+ .to raise_error(ArgumentError, error_message('.'))
+ expect { version('a.b.c') }
+ .to raise_error(ArgumentError, error_message('a.b.c'))
+ expect { version(version('321312..')) }
+ .to raise_error(ArgumentError, error_message('321312..'))
+ end
end
- it 'creates an object with instance' do
- expect( Version.new(Version.new('1.2.3.4')) ).to be_instance_of(Version)
- expect( Version.new(Version.new('0')) ).to be_instance_of(Version)
- expect( Version.new(Version.new('')) ).to be_instance_of(Version)
- expect( Version.new(Version.new) ).to be_instance_of(Version)
+ context 'when another version is passed' do
+ it 'raises ArgumentError for invalid input' do
+ expect { version(version('1.')) }
+ .to raise_error(ArgumentError, error_message('1.'))
+ expect { version(version('.3')) }
+ .to raise_error(ArgumentError, error_message('.3'))
+ expect { version(version('0..3')) }
+ .to raise_error(ArgumentError, error_message('0..3'))
+ expect { version(version('.3.')) }
+ .to raise_error(ArgumentError, error_message('.3.'))
+ expect { version(version('.')) }
+ .to raise_error(ArgumentError, error_message('.'))
+ end
end
+ end
- it 'doesn`t raise error' do
- expect { Version.new(Version.new('1.2.3')) }.to_not raise_error
- expect { Version.new('1.2.3') }.to_not raise_error
- expect { Version.new('1.2.0') }.to_not raise_error
- expect { Version.new('') }.to_not raise_error
- expect { Version.new('0') }.to_not raise_error
- expect { Version.new }.to_not raise_error
+ describe '#<=>' do
+ it 'compares using ==' do
+ expect(version('1.1.0')).to be == version('1.1')
+ expect(version('1.1')).to be == version('1.1')
+ expect(version('')).to be == version('0')
+ expect(version('1')).to be == version('1.0.0.0')
+ expect(version('0')).to be == version('0.0.0.0')
end
- it 'raises error' do
- string = '1.'
- message = "Invalid version string \'#{string}\'"
- expect { Version.new(string) }.to raise_error(ArgumentError, message)
- string = '.3'
- message = "Invalid version string \'#{string}\'"
- expect { Version.new(string) }.to raise_error(ArgumentError, message)
- string = '0..3'
- message = "Invalid version string \'#{string}\'"
- expect { Version.new(string) }.to raise_error(ArgumentError, message)
- string = '3,4'
- message = "Invalid version string \'#{string}\'"
- expect { Version.new(string) }.to raise_error(ArgumentError, message)
- string = 'abc'
- message = "Invalid version string \'#{string}\'"
- expect { Version.new(string) }.to raise_error(ArgumentError, message)
- string = 'a.b.c'
- message = "Invalid version string \'#{string}\'"
- expect { Version.new(string) }.to raise_error(ArgumentError, message)
+ it 'compares using >' do
+ expect(version('1.2.3')).to be > version('1.2.2')
+ expect(version('1.2.3')).to be > version('')
+ expect(version('1.1')).to be > version('1')
+ expect(version('1.0.1')).to be > version('1.0.0')
end
- end
- describe '#<=>' do
- it 'compares versions' do
- expect(Version.new('1.1.0')).to eq(Version.new('1.1'))
- expect(Version.new('1.1')).to eq(Version.new('1.1'))
- expect(Version.new('0.1')).not_to eq(Version.new('1'))
- expect(Version.new('1.2.3')).to be < Version.new('1.3')
- expect(Version.new('1.2.3')).to be < Version.new('1.3.1')
- expect(Version.new('')).to eq(Version.new)
+ it 'compares using <' do
+ expect(version('1.2.3')).to be < version('1.3')
+ expect(version('1.2.3')).to be < version('1.3.1')
+ expect(version('1')).to be < version('1.1')
+ expect(version('1.3.2')).to_not be < version('1.2')
end
+
+ it 'compares using >=' do
+ expect(version('1.3.2')).to be >= version('1.3.2')
+ expect(version('1.3.2')).to be >= version('1.3')
+ expect(version('')).to_not be >= version('1')
+ end
+
+ it 'compares using <=' do
+ expect(version('1')).to be <= version('1')
+ expect(version('1.2')).to be <= version('1.3')
+ expect(version('')).to be <= version('0')
+ end
end
describe '#to_s' do
it 'converts to string' do
- expect(Version.new('1.1.0').to_s).to eq('1.1')
- expect(Version.new('1.1').to_s).to eq('1.1')
- expect(Version.new('').to_s).to eq('')
- expect(Version.new.to_s).to eq('')
- expect(Version.new(Version.new('1.2.3')).to_s).to eq('1.2.3')
+ expect(version('1.1.0').to_s).to eq('1.1')
+ expect(version('1.1').to_s).to eq('1.1')
+ expect(version('').to_s).to eq('')
+ expect(version('0').to_s).to eq('')
+ expect(version(version('1.2.3')).to_s).to eq('1.2.3')
end
end
+ # => #components must not allow version modification!
describe '#components' do
- it 'breaks into components' do
- expect(Version.new('1.3.5').components).to match_array([1, 3, 5])
- expect(Version.new('1.3.5.0').components).to match_array([1, 3, 5])
- expect(Version.new('1.0.0.0').components).to match_array([1])
- expect(Version.new('').components).to match_array([])
+ context 'when no optional parameter is given' do
+ it 'breaks into components' do
+ expect(version('1.3.5').components).to eq [1, 3, 5]
+ end
+
+ it 'excludes zeros at the end' do
+ expect(version('1.3.5.0').components).to eq [1, 3, 5]
+ expect(version('1.0.0.0').components).to eq [1]
+ end
+
+ it 'returns empty list for version 0' do
+ expect(version('').components).to eq []
+ end
end
- it 'breaks into N components' do
- expect(Version.new('1.3.5').components(1)).to match_array([1])
- expect(Version.new('1.3.5').components(2)).to match_array([1, 3])
- expect(Version.new('1.3.5').components(3)).to match_array([1, 3, 5])
- expect(Version.new('1.3.5.0').components(3)).to match_array([1, 3, 5])
- expect(Version.new('1.3.5').components(4)).to match_array([1, 3, 5, 0])
- expect(Version.new('1.3.5').components(0)).to match_array([1, 3, 5])
- expect(Version.new('').components(4)).to match_array([0, 0, 0, 0])
+ context 'when optional parameter is given' do
+ it 'breaks into N components' do
+ expect(version('1.3.5').components(1)).to eq [1]
+ expect(version('1.3.5').components(2)).to eq [1, 3]
+ expect(version('1.3.5').components(3)).to eq [1, 3, 5]
+ expect(version('1.3.5.0').components(3)).to eq [1, 3, 5]
+ expect(version('1.3.5').components(4)).to eq [1, 3, 5, 0]
+ expect(version('1.3.5').components(0)).to eq [1, 3, 5]
+ expect(version('').components(4)).to eq [0, 0, 0, 0]
+ end
end
+
+ it 'doesn`t modify the instance' do

Идеята не е да провериш дали components поврежда инстанцията като се викне, а дали components може да се използва, за да се промени инстанцията.

Освен това, object_id-то на инстанцията никога няма да се промени. Каквото и да й правиш.

Промени решението, така че да няма dup, зареди файла в едно irb и се опитай да пресъздадеш проблема. После го направи на тест.

+ instance = version('1.3.5')
+ id_before = instance.object_id
+ instance.components(1)
+ id_after = instance.object_id
+ expect(id_before).to eq id_after
+ end
end
describe 'Version::Range' do
describe '.new' do
- it 'valid input' do
- expect(Version::Range.new(Version.new('1.0.0'), Version.new('2.0.0')))
- .to be_instance_of(Version::Range)
- expect(Version::Range.new('1.0.0', '2.0.0'))
- .to be_instance_of(Version::Range)
+ context 'when version is not valid' do
+ it 'raises ArgumentError' do
+ argument = '1.0.0.'
+ expect { Version::Range.new(version(argument), version('2.0.0')) }
+ .to raise_error(ArgumentError, error_message(argument))
+ expect { Version::Range.new(version(''), version(argument)) }
+ .to raise_error(ArgumentError, error_message(argument))
+ expect { Version::Range.new(argument, '2.0.0') }
+ .to raise_error(ArgumentError, error_message(argument))
+ end
end
-
- it 'invalid input' do
- string = '1.0.0.'
- message = "Invalid version string \'#{string}\'"
- expect { Version::Range.new(Version.new(string), Version.new('2.0.0')) }
- .to raise_error(ArgumentError, message)
- expect { Version::Range.new(string, '2.0.0') }
- .to raise_error(ArgumentError, message)
- end
end
describe '#include?' do
- it 'includes an instance' do
- range = Version::Range.new(Version.new('1'), Version.new('2'))
- expect(range.include?(Version.new('1.5'))).to be true
+ context 'when an instance is passed' do
+ it 'includes given version' do
+ range = Version::Range.new(version('1'), version('2'))
+ expect(range.include?(version('1.5'))).to be true
+ expect(range.include?(version('1'))).to be true
+ expect(range.include?(version('1.0.0'))).to be true
+ expect(range.include?(version('2.1'))).to be false
+ expect(range.include?(version(''))).to be false
+ expect(range.include?(version('2'))).to be false
+ end
end
- it 'includes a string' do
- range = Version::Range.new(Version.new('1'), Version.new('2'))
- expect(range.include?('1.5')).to be true
+ context 'when a string is passed' do
+ it 'includes given version' do
+ first_version = version('1')
+ second_version = version('2')
+ range = Version::Range.new(first_version, second_version)
+ expect(range.include?('1.5')).to be true
+ expect(Version.new('1.5')).to be >= first_version
+ expect(Version.new('1.5')).to be < second_version
+ expect(range.include?('1')).to be true
+ expect(range.include?('1')).to be true
+ expect(range.include?('1.0.0')).to be true
+ expect(range.include?('2.1')).to be false
+ expect(range.include?('')).to be false
+ expect(range.include?('2')).to be false
+ end
end
end
+ # => #to_a, works only for versions with up to 3 components
describe '#to_a' do
- it 'includes first and exludes last' do
- range = Version::Range.new(Version.new('1.1.0'), Version.new('1.2.2'))
- expect(range.to_a).to include('1.1')
- expect(range.to_a).not_to include('1.2.2')
+ context 'when equal versions are passed' do
+ it 'returns empty list' do
+ range = Version::Range.new('1.1', '1.1')
+ expect(range.to_a).to be_empty
+ end
end
- it 'doesn`t list versions for equal ones' do
- range = Version::Range.new('1.1', '1.1')
- expect(range.to_a).to eq([])
- end
+ context 'when first version > second version' do
+ it 'generates all versions between first and second version' do
+ range = Version::Range.new('1.1.0', '1.1.2')
+ expect(range.to_a).to eq ['1.1', '1.1.1']
+ expect(range.to_a).to_not eq ['1.1', '1.1.1', '1.1.2']
+ expect(range.to_a).to_not eq ['1.1.0', '1.1.1', '1.1.2']
- it 'lists all versions' do
- expect(Version::Range.new('1.1.0', '1.2.2').to_a).to eq \
- [
- '1.1', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', \
- '1.1.6', '1.1.7', '1.1.8', '1.1.9', '1.2', '1.2.1'
+ range = Version::Range.new(version('1.1.0'), version('1.2.2'))
+ expect(range.to_a).to eq [
+ '1.1', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', '1.1.6', \
+ '1.1.7', '1.1.8', '1.1.9', '1.2', '1.2.1'
]
- expect(Version::Range.new('1.1', '1.2').to_a).to eq \
- [
+
+ range = Version::Range.new('1.1', '1.2')
+ expect(range.to_a).to eq [
'1.1', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', \
'1.1.6', '1.1.7', '1.1.8', '1.1.9'
]
+
+ range = Version::Range.new('', '')
+ expect(range.to_a).to eq []
+ end
end
end
end
end

Цветан обнови решението на 18.11.2016 09:32 (преди почти 2 години)

RSpec.describe 'Version' do
def version(argument)
version_obj.new(argument)
end
def error_message(string)
"Invalid version string \'#{string}\'"
end
let(:version_obj) { Version }
describe '.new' do
context 'when string is passed' do
it 'raises ArgumentError for invalid input' do
expect { version('1.') }
.to raise_error(ArgumentError, error_message('1.'))
expect { version('.3') }
.to raise_error(ArgumentError, error_message('.3'))
expect { version('0..3') }
.to raise_error(ArgumentError, error_message('0..3'))
expect { version('.3.') }
.to raise_error(ArgumentError, error_message('.3.'))
expect { version('.') }
.to raise_error(ArgumentError, error_message('.'))
expect { version('a.b.c') }
.to raise_error(ArgumentError, error_message('a.b.c'))
expect { version(version('321312..')) }
.to raise_error(ArgumentError, error_message('321312..'))
end
end
context 'when another version is passed' do
it 'raises ArgumentError for invalid input' do
expect { version(version('1.')) }
.to raise_error(ArgumentError, error_message('1.'))
expect { version(version('.3')) }
.to raise_error(ArgumentError, error_message('.3'))
expect { version(version('0..3')) }
.to raise_error(ArgumentError, error_message('0..3'))
expect { version(version('.3.')) }
.to raise_error(ArgumentError, error_message('.3.'))
expect { version(version('.')) }
.to raise_error(ArgumentError, error_message('.'))
end
end
end
describe '#<=>' do
it 'compares using ==' do
expect(version('1.1.0')).to be == version('1.1')
expect(version('1.1')).to be == version('1.1')
- expect(version('')).to be == version('0')
+ expect(version('')).to be == version('0')
expect(version('1')).to be == version('1.0.0.0')
expect(version('0')).to be == version('0.0.0.0')
end
it 'compares using >' do
expect(version('1.2.3')).to be > version('1.2.2')
expect(version('1.2.3')).to be > version('')
expect(version('1.1')).to be > version('1')
expect(version('1.0.1')).to be > version('1.0.0')
end
it 'compares using <' do
expect(version('1.2.3')).to be < version('1.3')
expect(version('1.2.3')).to be < version('1.3.1')
expect(version('1')).to be < version('1.1')
expect(version('1.3.2')).to_not be < version('1.2')
end
it 'compares using >=' do
expect(version('1.3.2')).to be >= version('1.3.2')
expect(version('1.3.2')).to be >= version('1.3')
expect(version('')).to_not be >= version('1')
end
it 'compares using <=' do
expect(version('1')).to be <= version('1')
expect(version('1.2')).to be <= version('1.3')
expect(version('')).to be <= version('0')
end
end
describe '#to_s' do
it 'converts to string' do
expect(version('1.1.0').to_s).to eq('1.1')
expect(version('1.1').to_s).to eq('1.1')
expect(version('').to_s).to eq('')
expect(version('0').to_s).to eq('')
expect(version(version('1.2.3')).to_s).to eq('1.2.3')
end
end
- # => #components must not allow version modification!
describe '#components' do
context 'when no optional parameter is given' do
it 'breaks into components' do
expect(version('1.3.5').components).to eq [1, 3, 5]
end
it 'excludes zeros at the end' do
expect(version('1.3.5.0').components).to eq [1, 3, 5]
expect(version('1.0.0.0').components).to eq [1]
end
it 'returns empty list for version 0' do
expect(version('').components).to eq []
end
end
context 'when optional parameter is given' do
it 'breaks into N components' do
expect(version('1.3.5').components(1)).to eq [1]
expect(version('1.3.5').components(2)).to eq [1, 3]
expect(version('1.3.5').components(3)).to eq [1, 3, 5]
expect(version('1.3.5.0').components(3)).to eq [1, 3, 5]
expect(version('1.3.5').components(4)).to eq [1, 3, 5, 0]
expect(version('1.3.5').components(0)).to eq [1, 3, 5]
expect(version('').components(4)).to eq [0, 0, 0, 0]
end
end
it 'doesn`t modify the instance' do
- instance = version('1.3.5')
- id_before = instance.object_id
- instance.components(1)
- id_after = instance.object_id
- expect(id_before).to eq id_after
+ instance = version('1.2.3')
+ expect { instance.components }.to_not change { instance }
+ expect { instance.components(1) }.to_not change { instance }
+ expect { instance.components(2) }.to_not change { instance }
+ expect { instance.components(3) }.to_not change { instance }
+ expect { instance.components(4) }.to_not change { instance }
end
end
describe 'Version::Range' do
describe '.new' do
context 'when version is not valid' do
it 'raises ArgumentError' do
argument = '1.0.0.'
expect { Version::Range.new(version(argument), version('2.0.0')) }
.to raise_error(ArgumentError, error_message(argument))
expect { Version::Range.new(version(''), version(argument)) }
.to raise_error(ArgumentError, error_message(argument))
expect { Version::Range.new(argument, '2.0.0') }
.to raise_error(ArgumentError, error_message(argument))
end
end
end
describe '#include?' do
context 'when an instance is passed' do
it 'includes given version' do
range = Version::Range.new(version('1'), version('2'))
expect(range.include?(version('1.5'))).to be true
expect(range.include?(version('1'))).to be true
expect(range.include?(version('1.0.0'))).to be true
expect(range.include?(version('2.1'))).to be false
expect(range.include?(version(''))).to be false
expect(range.include?(version('2'))).to be false
end
end
context 'when a string is passed' do
it 'includes given version' do
first_version = version('1')
second_version = version('2')
range = Version::Range.new(first_version, second_version)
expect(range.include?('1.5')).to be true
- expect(Version.new('1.5')).to be >= first_version
- expect(Version.new('1.5')).to be < second_version
expect(range.include?('1')).to be true
expect(range.include?('1')).to be true
expect(range.include?('1.0.0')).to be true
expect(range.include?('2.1')).to be false
expect(range.include?('')).to be false
expect(range.include?('2')).to be false
end
end
end
- # => #to_a, works only for versions with up to 3 components
describe '#to_a' do
context 'when equal versions are passed' do
it 'returns empty list' do
range = Version::Range.new('1.1', '1.1')
expect(range.to_a).to be_empty
end
end
context 'when first version > second version' do
it 'generates all versions between first and second version' do
range = Version::Range.new('1.1.0', '1.1.2')
expect(range.to_a).to eq ['1.1', '1.1.1']
expect(range.to_a).to_not eq ['1.1', '1.1.1', '1.1.2']
expect(range.to_a).to_not eq ['1.1.0', '1.1.1', '1.1.2']
range = Version::Range.new(version('1.1.0'), version('1.2.2'))
expect(range.to_a).to eq [
'1.1', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', '1.1.6', \
'1.1.7', '1.1.8', '1.1.9', '1.2', '1.2.1'
]
range = Version::Range.new('1.1', '1.2')
expect(range.to_a).to eq [
'1.1', '1.1.1', '1.1.2', '1.1.3', '1.1.4', '1.1.5', \
'1.1.6', '1.1.7', '1.1.8', '1.1.9'
]
range = Version::Range.new('', '')
expect(range.to_a).to eq []
end
end
end
end
end