Решение на Четвърта задача - Unit тестване от Мариян Асенов
Резултати
- 5 точки от тестове
- 0 бонус точки
- 5 точки общо
- 15 успешни тест(а)
- 4 неуспешни тест(а)
Код
Лог от изпълнението
...FF.F.....F......
Failures:
1) spec Version checks that initialize can be given an empty string
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 /\A[0-9]+(\.[0-9]+)*\z/.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-1z0v1z6/spec.rb:295: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 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-1z0v1z6/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)>'
3) 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-1z0v1z6/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)>'
4) spec Version::Range tests constructing ranges with strings
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 = start_version
@end_version = 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-1z0v1z6/spec.rb:479: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 16.37 seconds
19 examples, 4 failures
Failed examples:
rspec /tmp/d20161119-19072-1z0v1z6/spec.rb:279 # spec Version checks that initialize can be given an empty string
rspec /tmp/d20161119-19072-1z0v1z6/spec.rb:298 # spec Version checks that initialize can be given no arguments
rspec /tmp/d20161119-19072-1z0v1z6/spec.rb:353 # spec Version checks for comparison operators negatively
rspec /tmp/d20161119-19072-1z0v1z6/spec.rb:471 # spec Version::Range tests constructing ranges with strings
История (8 версии и 16 коментара)
Мариян обнови решението на 17.11.2016 15:05 (преди почти 9 години)
Тези две променливи защо са ти?
Разделяй тези блокове с по един празен ред. Ще изглежда много по-прегледно.
Каква е разликата между match_array и eq?
Това очевидно няма да промени нищо. Махни .dup от имплементацията на components и виж какво може да се случи.
Това подравняване е изключително гадно. И преди да кажеш "Rubocop ме накара", виж следното:
expect(
Version::Range.new(Version.new('1'), Version.new('2')).include?(Version.new('0.9')
).to be false
или по-добре, изкарай една променлива за range-а и използвай .to_not include вместо .to be false
Моля те, махни тази скоба, защото подсъзнателно искам да ти отнема точка само заради нея.
expect(array_of_versions).to match_array [
Version.new('1.1.0'),
Version.new('1.1.1'),
Version.new('1.1.2')
]
Мариян обнови решението на 17.11.2016 17:13 (преди почти 9 години)
Оставих я втората променлива, защото стават повече от 80 символа, ако сложа стринга като аргумент на raise_error
Мариян обнови решението на 17.11.2016 17:46 (преди почти 9 години)
expect { Version.new(0..2) }.to raise_error(
ArgumentError,
"Invalid version string '0..2'"
)
Не разбирам този тест какво прави тук.
Ами мислех си, че трябва да проверяваме дали #to_s не променя обекта.
Мариян обнови решението на 17.11.2016 19:59 (преди почти 9 години)
Кое те наведе на тази мисъл?
Тоест не е проблем и да променя обекта и да не тествам за този случай? Тъй като в условието на задачата не е споменато дали го променя или не
Тоест не е проблем и да променя обекта и да не тествам за този случай? Тъй като в условието на задачата не е споменато дали го променя или не
Тоест не е проблем и да променя обекта и да не тествам за този случай? Тъй като в условието на задачата не е споменато дали го променя или не
В другия метод ако не се внимава - може да се промени обектът. Тук няма реална опасност да стане това. Не се връща нищо свързано със състоянието на версията.
Просто няма логика някога това да се счупи. Иначе, предполагам не би тествал дали <, >, <=, >=, ==, <=>, Version::Range.new и всички останали методи променят обекта. Защо тогава да тестваш само този?
Добре съгласих се!
