#ruby-on-rails #ruby-on-rails-3
#ruby-on-rails #ruby-on-rails-3
Вопрос:
Привет, у меня небольшая проблема с прохождением моих модульных тестов. В частности, те, что в *cart_test.rb *, терпят неудачу.
test "add two different items" do
cart = Cart.create
book_one = products(:one)
book_two = products(:two)
cart.add_product(book_one.id).save!
cart.add_product(book_two.id).save!
assert_equal 2, cart.line_items.size
assert_equal book_one.price book_two.price, cart.total_price
end
test "add two unique items" do
cart = Cart.create
ruby_book = products(:ruby)
cart.add_product(ruby_book.id).save!
cart.add_product(ruby_book.id).save!
assert_equal 2*ruby_book.price, cart.total_price
assert_equal 1, cart.line_items.size
assert_equal 2, cart.line_items[0].quantity
end
Вот мой репозиторий: https://github.com/zackster/Agile-Web-Development-w—Rails—-DEPOT-application
Может кто-нибудь, пожалуйста, помочь мне понять, что происходит? Я полагаю, что тесты терпят неудачу, потому что товары на самом деле не добавляются в корзину, но это может быть что-то совсем другое [я новичок в rails] . . . спасибо!
Комментарии:
1. Похоже, что модульные тесты делают то, что они должны делать, и у самой программы есть проблемы.
2. Я согласен.. итак, почему у программы проблемы?
3. Это ужасно большой вопрос. Как выглядит ошибка?
Ответ №1:
Тесты CartTest терпят неудачу, потому что в Cart::add_product вы фактически не привязываете новый line_item к корзине — просто создаете потерянные line_items с raw LineItem.create
. Чтобы привязаться к корзине, вы можете изменить строку, которая создавала LineItem, не имеющую отношения к корзине:
current_item = LineItem.new(:product_id => product_id, :price => product_price)
чтобы фактически создать новую позицию в коллекции line_items текущей корзины:
current_item = line_items.create(:product_id => product_id, :price => product_price)
Были некоторые другие сбои, о которых вы специально не спрашивали, но я все равно изучил их…
Ваши продукты.yml не указывает поле id, поэтому product_id равен 1 в line_items.в конечном итоге yml не ссылается ни на один продукт при запуске fixtures. Вы можете создавать жесткий код id: 1
и т.д. В своих продуктах.yml для решения этой проблемы.
Далее, есть просто опечатка в CartsControllerTest — @cart_id
не определено, и вместо этого должно быть @cart.id
Наконец, это выявляет еще одну проблему, которая на самом деле является логической проблемой. Теперь ваш тест на уничтожение продукта завершается неудачей, но на самом деле это потому, что ваша логика не позволяет вам уничтожить продукт, у которого есть line_items (что ваш продукт делает, как только мы исправили продукты.файл yml с указанными идентификаторами). Итак … на самом деле тест неверен, и код, я полагаю, находится прямо там.
Комментарии:
1. Кстати, чтобы объяснить эту конструкцию line_items.create, ваш продукт определяется с помощью
has_many
line_items . Итак, из-за этого вы можете ссылаться на line_items в контексте продукта. Rails предоставляет вам множество автоматически сгенерированных методов для элементов has_many. Больше можно найти здесь: api.rubyonrails.org/classes/ActiveRecord/Associations / … и это пример использованияothers.create(...)
2. Где находится тест для уничтожения продукта, который терпит неудачу? Кстати, теперь, когда я смотрю на product.rb (строка 21), у меня есть «if line_items.count.zero?». Должно ли вместо этого быть «if self.line_items.count.zero?» ? Еще раз спасибо за супер полезный ответ!
3.
line_items.count.zero?
это нормально, но проблема в том, что у вас действительно есть некоторые позиции, соответствующие вашему продукту (теперь, когда на них ссылаются приспособления), поэтому ваш собственный код не позволит вам удалить его. Итак, вы, вероятно, захотите изменить свой тест, чтобы быть уверенным, что в этом случае удаление завершится неудачей, вместо того, чтобы ожидать, что оно завершится успешно. И затем вы могли бы добавить еще один тест, который пытается удалить продукт, в котором нет позиций, что должно увенчаться успехом. Рад, что это было полезно 🙂