WIP: Reduce use of Selenium in favour of rack-test#6497
WIP: Reduce use of Selenium in favour of rack-test#6497pablobm wants to merge 4 commits intoopenstreetmap:masterfrom
Conversation
|
I'm not familiar with Presumably it's not actually using a browser so all you're really doing is checking that the expected HTML is returned? So what does it offer over a controller or integration test? |
|
Right, that's exactly it. The difference with controller tests is that you get to browse across different controllers, not just the one. The difference with integration tests is that you browse via clicking links, submitting forms, etc, as opposed as sending low-level HTTP requests. In general, my view is that it's best to avoid Selenium unless you really need JS. In this case, the tests involved typically are about the profile section and similar, which don't need JS most of the time. Anywhere we think the JS is relevant, we can add back. The implementation would look something like "Selenium by default, except in these tests where we use rack-test" or the other way around. |
|
I'd be happy to see the tests updated to use rack-test by default, and a full browser only when needed for full javascript execution. I don't think there's any noticeable gap between the html generation of rack-test and a browser, whereas there were often issues back in the poltergeist-vs-real-browser days for JS execution. For me, the "visit link" style testing is the most important bit. I'd prefer if the controller-style and integration-style tests were all rewritten away from raw POSTs etc (apart from the tests that deliberately try to inject incorrect form submissions to validate the error handling) but that's such a huge project I've never thought it was worthwhile. I'm used to using rspec in other projects, and only tagging the specific system tests that need javascript with an option, e.g. |
|
So as @gravitystorm says I know he's long been keen to move away from controller and integration tests to system tests and I understand the logic that you're actually properly testing the behaviour of the site as the user interacts with it but the downside has always been the cost in time/resources of running everything through selenium. So it sounds like this is a solution to that but with the downside that you're really testing how the site will behave in a browser any more. Is there a tension here with more use of turbo? Presumably rack-test won't be doing any additional loads that turbo might call for either or will it? |
|
100% agree with leaving controller/integration tests for low-level testing. My experience is that these are typically used for testing specific technical details, variants of "happy paths" reflected in system tests, and malicious usage of APIs. My main experience is also with RSpec with the syntax shared by @gravitystorm. I want to think that with minitest it can be done with something like Re: Turbo, yes, that's a tradeoff. With rack-test, links and form submissions will always trigger full-page loads. This creates a difference between what the tests do and real users do. At this point the question is: how much do we trust Rails to do what it promises to do? When using an external tool, we want to think that we don't need to test the tool itself, but just the things we do with the tool, if that makes sense. Having said that, things can go wrong for example if something is misconfigured, etc. Eg: if we don't label a turbo frame correctly by mistake. Still we can go on a case-by-case basis. For example using Selenium only for the happy paths, or for specific situations where there's a known risk. In exchange, we gain a faster execution of the test suite, a reduction of flaky tests, and more easily debuggable system tests. |
I have the "behave like a browser" split into two aspects in my mind:
I live in hope that someone can create something that's much closer to a real browser, in terms of layout engines and js execution, without having to actually be an entire browser and all the headaches that brings. |
So I think the only approach is to be more explicit with choosing the driver in each class or in specific tests. Something like: class MixedDriverTest < ApplicationSystemTestCase
driven_by :rack_test # default
test "simple non-JS test" do
visit "/status"
assert_text "OK"
end
test "switch to selenium just for this test" do
using_driver(:selenium, using: :chrome) do
visit "/dashboard"
# JS interactions here
assert_selector ".map"
end
end
endI would probably default to test "switch to selenium just for this test" do
using_javascript do
visit "/dashboard"
# JS interactions here
assert_selector ".map"
end
endI'd be interested in a comparison of test suite runtimes, to see if it's worthwhile. |
3408925 to
9a7d689
Compare
Generated by 🚫 Danger |
87c1de7 to
4f43265
Compare
|
I had another pass at this, converting a few tests for comparison. At the moment I'm seeing the combination of Selenium+rack-test running in ~2/3 of the time it takes to run with Selenium only. For example: in my machine I ran a handful of converted tests (see The DX story is not great at the moment. For each test class, the individual tests need to be grouped as follows: class AccountDeletionTest < ApplicationSystemTestCase
class JsTest < AccountDeletionTest
driven_by_selenium
test "this requires selenium" do
# ...
end
end
# These need to go into its own subclass. Otherwise
# JsTest above will also run the "html tests",
# because as a subclass it will contain them
# in addition to its own "js tests".
class HtmlTest < AccountDeletionTest
# `driven_by :rack_test` is already default
test "this will work with just rack-test" do
# ...
end
end
# And in addition this will run three times: two
# with rack-test and one with Selenium, because
# minitest detects the superclass and both subclasses
# as containining it.
test "some test" do
# ...
end
endNot a huge deal, we could come up with something more ergonomic. For example we could have |
|
One option would be to split up tests so that any one file was all selenium or all rack test and then you just need to add The down side of that is that it might mean splitting up tests which are related and which would make more sense being grouped together? |
Yeah, that was my thought. |
|
Tried to put together some metaprogramming to provide a
Putting to rest for now until I can come up with better ideas that are not overly clever. |
4f43265 to
152aa19
Compare
|
Closing this as I'm not liking the options. |
Just a proposal: would it make sense to use rack-test for system tests, where possible?
If we can reduce the use of Selenium, the test suite will run faster and more reliably. The code in this PR is just a quick experiment, showing that only 40% of system tests need Selenium. The relevant output is the following: