Skip to content

Conversation

@geneux
Copy link
Owner

@geneux geneux commented Sep 24, 2016

No description provided.

second_answer = create(:answer, question: question, user: user)
visit question_path(question)
within("#answer-#{second_answer.id}") { click_on 'Star' }
sleep 0.1
Copy link
Owner Author

@geneux geneux Sep 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Я не совсем понял, из-за чего точно, но таймаут капибары перестал успевать примерно на 100мс. Видимо, как раз в это время Сфинкс перестраивает дельта-индексы. Считаю, что костыль, но ничего умнее придумать не смог. И почему-то проявилось только в этом тесте.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ох, ну тут с тестом проблемка, конечно. Зачем нам проверять id элемента? Это уже не пользовательский сценарий, а кодерский. Надо проверять контент, используя have_content, который автоматически подождет до появления контента и избавить от костыля в виде sleep.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да, правда, можно было проще проверить. И, действительно, после переделки на have_content стало дожидаться. Не задумался, видимо, когда писал, что ждет именно он.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вот рано я обрадовался. Вызов have_content вообще не помогает, ну, точно Сфинкс перестраивает дельты и блокирует объект в транзакции, его надо еще ждать.

Получилось так: заметил, что CI показывает битые тесты. Посмотрел. API стало работать иначе -- порядок Answer-ов в ответе API поменялся на обратный. Так как явно он нигде не задавался, подумал, и поставил уж для большего педантизма default_scope во всех моделях, которые что-то отображают. Спеки API прошли. А этот тест снова стал заваливаться.

В итоге вернул sleep 0.1, так как единственный вариант получается -- делать флаг ожидания индексации Сфинкса или завершения транзакции, и все равно делать в спеке вызов ожидания. Так как готовность Сфинкса и так проверяется через 100мс, то пусть уж лучше тут будет sleep, медленнее от него точно не станет по сравнению с предложенным методом.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have_content сам за тебя ждет, столько, сколько нужно. Ты как-то неправильно его используешь, значит. Ты, вероятно, оставил что-то вроде expect(page.first('div')).to have_content(...)?

Нужно так:

# сужаем область, в которой будет производится поиск элементов
within "#answers div:first-child" do # а лучше использовать имя класса "#answers .answer:first-child"
  expect(page).to have_content(...)
end

Когда ты делаешь page.first(...), то возвращается тот элемент, который был первым в момент вызова, и тут уже не помогает have_content.

Copy link
Owner Author

@geneux geneux Sep 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Вообще, я это понял, исключил даже within и для проверки сделал вот так:

      # sleep 0.1
      expect(page).to have_content second_answer.body

И без комментарием тест работает, с комментарием -- валится. Но с #answers div:first-child мне вариант больше нравится, переделаю на него. C #answers .answer хоть и лаконичнее, но хуже читается, менее понятно, что выделяется.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Попробовал, не получается ни с #answers div:first-child, ни c #answers .answer (у меня в текущей ветке нет класса answer, но для эксперимента я его добавил). Всегда валится на Capybara::Ambiguous, например с: Ambiguous match, found 2 elements matching css "#answers .answer". Пробую из JS-консоли: один элемент. Странно.

В итоге sleep оставил, и have_content перед ним тоже, хотя, он не спасает совершенно. Думаю, варианты с селекторами, даже если он их смэтчит правильно, не пройдут тоже.

В итоге, это лучшее, что работает.

end
end

shared_examples :sphinx_search_controller_with_params do |entity, attribute, search_type, validity = true|
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Возможно, здесь с shared example-ом я немного "перехимичил", зато получилось весьма лаконичная сама спека

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Перехимичил", разве что, с расположением примеров.
В данном случае лучше сами shared_examples объявить в файле-спеке самого контроллера. Сейчас спека контроллера – сплошная магия, ее нельзя взять и прочитать, как спецификацию.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Самое смешное, что я так их и писал, потом выносил в отдельный файл. Именно, чтобы пока пишешь, не запутаться )). Понял, вернул в спеку.

@@ -0,0 +1,28 @@
class SearchService
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ну уверен, что правильнее: помещать сервисный объект в модели, или делать еще одну папку в /app и прописывать её в пути загрузки приложения? Пока объект всего один, положил в модели, чтобы не разветвлять дерево проекта.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Делать еще одну папку, app/services.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ок, сделал, переместил.

@@ -0,0 +1,28 @@
class SearchService
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Делать еще одну папку, app/services.

private

def klass(type)
case type
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не очень мне нравится такой подход, у нас все-таки Ruby, можно применить что-нибудь из мета-программирования.
Например, получать с клиента не однобуквенные типы, а полные ("question", "answer"), и делать classify.constantize, предварительно фильтруя, конечно.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да, это я понимаю, даже хотел так и сделать сначала, но тут немного меня смущает, то, что "снаружи" будет видно, какой класс у нас внутри приложения. Пока в нашем примере, они очевидны, то это все же не очень страшно, но если они будут более заковыристыми, я бы не рискнул их пользователю показывать в GET-запросах. Ок, это переделаю, даже спеки попроще станут.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Сделал, спеки лаконичнее сильно не стали, но зато вынес в константу сервис-объекта допустимые значения.

second_answer = create(:answer, question: question, user: user)
visit question_path(question)
within("#answer-#{second_answer.id}") { click_on 'Star' }
sleep 0.1
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ох, ну тут с тестом проблемка, конечно. Зачем нам проверять id элемента? Это уже не пользовательский сценарий, а кодерский. Надо проверять контент, используя have_content, который автоматически подождет до появления контента и избавить от костыля в виде sleep.

end
end

shared_examples :sphinx_search_controller_with_params do |entity, attribute, search_type, validity = true|
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Перехимичил", разве что, с расположением примеров.
В данном случае лучше сами shared_examples объявить в файле-спеке самого контроллера. Сейчас спека контроллера – сплошная магия, ее нельзя взять и прочитать, как спецификацию.

@geneux geneux mentioned this pull request Sep 25, 2016
@geneux
Copy link
Owner Author

geneux commented Sep 25, 2016

Несмотря на проблему с тестом, в котором приходится спать 100мс, думаю, можно двигаться дальше, PR пока оставлю открытым, но в мастер зарибейжу. Если что надо будет поправить -- поправлю в следующих ветках или между ними.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants