Problem/Motivation
No test coverage for the frontend.
Proposed resolution
Use Behat.
Discussed this with Jesse Beach, nod_ and Alex Pott yesterday at Dev Days (Szeged) and we strongly feel we should use Behat to get functional JavaScript test coverage in core. It gives us access to real browsers and phantomjs via mink, the tests are nicely self documenting with gherkin, lots of core developers are already familiar with it via client projects, it's used on Drupal.org etc. etc.
This wouldn't be a replacement for SimpleTest, but likely all the SimpleTests using the browser could be moved over.
There will be things we can't do with Behat, but we can tackle those separately.
Quote from catch's comment at #237566-159: Automated JavaScript unit testing framework.
I'd like to keep this issue clean and at a reasonable amount of comments. Let's file follow-ups for specific topics that needs to be agreed on, that worked very well for the JS meta clean-up.
Realistically we can't get started until we get at least a couple examples of implementation. I'll be talking with a few people this week already, I know jessebeach is as well. If you have a project using behat, please reach out to your closest JS maintainer to talk about it.
Remaining tasks
- Get feedback from projects using behat in the wild and sum that up somewhere.
- Reach out to Behat developers to see if/when they can help us out.
- Agree on how to implement this for core and contrib (where are test files, standards for writing tests, etc.).
- Make d.o testbot run behat tests
User interface changes
N/A.
API changes
Probably none, only additions.
People and groups involved
Drupal.org Infrastructure Working Group
Drupal.org Developer Tools Team
Groups.drupal.org Community Tools Leadership Team
| Comment | File | Size | Author |
|---|---|---|---|
| #98 | interdiff.txt | 12.32 KB | claudiu.cristea |
| #98 | 2232271-98-for-review-do-not-test.patch | 33.95 KB | claudiu.cristea |
| #98 | 2232271-98-full.patch | 3.12 MB | claudiu.cristea |
Comments
Comment #1
fgmI do have projects using Behat, but at the "whole site" level, not individual modules.
We've been extending the DrupalContext provided by DrupalExtension, as well as extending the Behat Buzz-based WebApiContext https://github.com/Behat/CommonContexts/blob/master/Behat/CommonContexts...
FWIW, (a) Behat 3 is almost launched and changes things a bit, (b) Buzz, which supports the WebApiContext it not very much alive and mixing Mink-derived steps with WebApi-derived steps doesn work (c) The WebApi context itself uses old-style includes, and already needs some tweaking to work with current practice.
All in all, with Rest getting such a larger role in current practice, we should use steps similar from the WebApi ones, but based on the Mink.
Not sure where this can take us regarding the larger issue you describe.
Comment #2
catchWe use Behat for several client projects at Tag1 as well, and also started a proof of concept for automated performance testing using it a while back.
Per https://github.com/Behat/Behat/issues/148 it looks like 3.0 supports running multiple suites at the same time, that would let us do $module/features with their own scenarios and context classes, as well as whatever site/profile level tests we'd want to ship with. Even without that we could collect tests outside behat and run them individually.
Two issues to open, but just putting notes here for now:
We should probably at least open an issue to look at porting DrupalExtension to 8.x/core. There's some things in there we probably can't rely on in core, like drush, but that's for the issue to sort out.
Also how to deal with the set up of the tested site, i.e. we'll need to have a clean install, but do we do that per scenario? per feature? Could we make it optional via a tag? Behat already has the events to handle this so it's mainly a choice on our side.
Comment #3
nod_Comment #4
jessebeach commentedComment #5
jessebeach commentedComment #6
dstolnod_ pointed me to this issue.
I'll note that this might lend an opportunity to remove the vendor directory from core. I would assume we would add drupalextenion, behat, mink, etc to require-dev. Granted, there is some overlap with core, but just adding composer.json below to an empty folder creates 12 mb of libraries, which might be fine, worth some discussion.
Comment #7
dstolUpdated #2229747: [d8] settings() has been removed and VERSION constant removed and was able to run a really simple behat test against 8 with no issues.
Comment #8
jhedstromDrush isn't mandatory, just one of the available drivers for communicating with Drupal. The Drupal driver would be the way to go. Drush is used for the testing of the extension itself (see
.travis.yml, and the bundled Behat features).I'd be interested in discussing an approach where the entire extension isn't forked and placed into core, but subcontexts for individual modules are created and put into core.
I'd really like to not see a clean site per scenario. Even per-feature seems overkill for this level of testing. That isn't to say that tests should rely on data created from previous scenarios, but if a reasonable effort is made for scenarios to clean up after themselves (the Drupal Extension currently clears out any users, nodes, and terms created during a scenario), then we can avoid re-installing for every feature, saving a tremendous amount of time spend on test runs.
Comment #9
larowlanHad a lengthy discussion with nod_ about this - here are the main points
Comment #10
catchYes, this means we'd add the Drupal driver to core, but the drush driver would stay in contrib.
I think we can handle isolation via a @tag on the scenarios, at least to start with. We know it's possible to do both isolated, and not-isolated tests, so we can figure that out later IMO.
I've personally used selenium+phantom but don't have a preference for that vs. zombie. The advantage of behat is apart from the test running environments and limitations in the browsers themselves, it's very little effort to switch.
Thanks for opening #2232861: Create BrowserTestBase for web-testing on top of Mink, following.
Comment #11
dstolWhat's the need to refactor the Drupal driver out of DrupalExtension and plop it into core? I don't understand the benefits vs vendoring.
Comment #12
catchCore APIs change very, very frequently. We also have a requirement that 100% of core tests pass all the time (i.e. a failing test prevents commits).
That means that any change to core that would break the Drupal driver, would either need a simultaneous commit to the driver, or some sort of bc layer added. This applies to both the driver and especially DrupalExtension.
While 8.x has added a lot of external dependencies to core, we currently don't have any core dependencies where core counts as 'upstream' pulled in via composer.
Comment #13
grasmash commentedI'd like to attempt to create a brief overview of the topics that needs to be discussed and the decisions that need to be made before Behat can become fully integration with Drupal, both on a core and on a contrib level.
We need to define a standard for the placement of various required Behat files. This includes:
We need to define standards around how each module creates a subcontext, which should contain custom step definitions. Suggestion: Every subcontext should be an extension of the main DrupalContext.
We need a tool that will aggregate all of the various Behat configuration settings and files provided by individual modules and provide them to Behat. A few requirements that come to mind:
We need to determine which session driver will be used by default for Javascript Behat tests. Some available options are: Selenium2 and Zombie.
Comment #14
grasmash commentedI've started a sandbox fork of D8 that introduces Behat testing into core. It is not yet functional, but if you're interested in commenting or contributing, it's here: https://drupal.org/sandbox/madmatter23/2239057
Comment #15
fgmItem 2 is no longer an issue: subcontexts are going away in Behat3, which is just a few days away from release at this point. The new suite-oriented Behat configuration may simplify our work in this regard.
Also, note that the WebApiContext I mentioned earlier is now a separate component, being completely redone for Behat 3.
Comment #16
grasmash commentedI was recently patching the Drupal Behat Extension to work with D8's new session management functions, and got into a conversation with sun regarding the Behat Extension's Drupal driver, which bootstraps Drupal and manually opens a session via the Drupal API. He brought up a good point:
As it applies to the Behat Extension, this comment suggests that we should not bootstrap Drupal at all. That would mean not using the Drupal driver. All interactions with Drupal should occur via a RESTful interface. To quote sun again:
The primary argument against this approach, as I see it, stems from performance concerns. It's faster to create entities with a simple entity_create() call than it is to make a GET request for a form, fill it out, and POST data back. However, this could be somewhat mitigated by sharing fixtures (set up steps) between scenarios in a given Behat feature.
This seems like an important topic to discuss before going to far with integrating Behat into core. Any thoughts?
Comment #17
moshe weitzman commentedI think it is OK to call into Drupal's API to do setup work like create entities. I dont think we have any choice. The REST API didn't get around to supporting all field types in core, and contrib will be worse. For example, we can't yet populate image/file fields using REST API.
I agree with Sun that all checking of functionality should happen via login form, link clicking, etc. I also abhor the shared state problem in Simpletest that Sun refers to. I just think we are falling into the same trap here. I guess I should look at the Drupal driver a bit closer.
Comment #18
fgmRelying only on the UI is a problem because once outside standalone core development, in actual site projects, themes can build screens differently, and make the core tests fail. The Behat extension currently addresses this by allowing the redefinition of a small number of strings or selectors to customize expectations, but to use Behat on a larger would require this sort of customization to be much more extensive.
Also, BDD is not just for UI, but also applies to web APIs, where the "customer" expectations are different, and tests are not expected to rely on a HTML UI, but (typically) only on JSON or XML exchanges. The interesting thing is that these are independent from theme, and can probably be independent of language too (another problem with UI-based tests), and can provide a more solid, and possibly faster, basis to build test contexts (loading fixtures), than working through the UI steps. That's what we did in a recent project, BTW.
In a typical Given/When/Then sequence, the three predicates must be expressed at business-level, but there is no reason why they would have to be implemented as such, especially (IMHO) for the Given, which is a starting point from which actual checks are done, and should probably be done as efficiently as possible, while the other two are more representative of the actual behaviour to be tested. Of course, the fact that the steps implementing G/W/T are exactly the same may make things a bit difficult.
Comment #19
jessebeach commentedAwesome, thanks for starting the sandbox grashmash!
We want to work in such a way that will allow us to easily propose changes to Drupal 8 core when this project reaches a state suitable for incorporation. So, let's make sure that any changes to core itself are associated with an issue and that that issue is tagged with Behat. Once we do reach the point where it becomes necessary to patch core, let's start a distribution project so we can track the patches.
Comment #20
grasmash commented@jessebeach I've actually already modified core in the sandbox. A step has been added to the installation process that configures the necessary behat.yml file.
Comment #21
sun@fgm: "UI" was not strictly meant to mean "HTML UI" in #16. Focus was on avoiding shared state (which implicitly means that booting a parallel Drupal and calling API functions should be avoided) and thus keeping the test runner strictly separated from site under test.
In fact, in an ideal world, all fixtures would be set up by performing RESTful HTTP requests (via REST module). — However, I was told that the RESTful server capabilities in core do not support config entities yet (which probably present the largest chunk of fixtures). I don't know how easy or hard it would be to resolve that blocker.
Comment #22
jessebeach commentedgrashmash, do you plan to do the bulk of the integration work in a module? Does that module exist yet?
Comment #23
grasmash commented@jessebeach I do not plan to house the initial integration in a module, although there may be a need for a module later on if we'd like to provide a UI. Currently, the plan is to for Behat code to live in two places: 1) in core .and 2) in the DrupalExtension library (which is not a module).
I've currently implemented the following additions to core:
In order to properly follow PSR-0/4, we may need to move and rename FeatureContext.php.
install.core.inc has also been modified so that it sets up the proper configuration in behat.yml during the install process.
I've also modified composer.json so that it downloads a couple of required Behat libraries, including the DrupalExtension, which will live in core/vendor.
Comment #24
grasmash commented@moshe @sun
We may not actually need a REST API in core in order to avoid the shared state problem. Behat can make GET and POST requests to the UI via the Goutte driver (which leverages Guzzle). This will work, but has two distinct disadvantages: 1) This will significantly slow down testing given that each set-up step will need to request fully-rendered pages from Drupal. 2) This will a LOT more legwork to modify the existing DrupalExtension library, which is already functional using the bootstrap approach.
Comment #25
moshe weitzman commentedAs I said before, I think it is fine to call into Drupal to do the GIVEN stop like setting up entities. It is just the WHEN/THEN steps that should be indepant of Drupal. I don't see how this violates the 'shared state' problem that Sun mentions. For starters, there is only one Drupal (at least in my head). The test runner is just the `behat` or `phpunit` unix programs. If we are talking about simpletest being the test runner, I'm no longer interested.
Comment #26
grasmash commented@moshe I'm inclined to agree with you, and I've already implemented the DrupalExtension so that it bootstraps Drupal and uses the existing GIVEN steps that utilize the Drupal API. Just wanted to make sure that all of the angles were considered.
Comment #27
jessebeach commentedre: #23, the Core modifications will be small and non-clashy, so in the interest of reducing friction, let's leave this as a Drupal sandbox for now and just make sure we merge in 8.x branch commits often. That will allow us to merge the change back into the 8.x branch later without conflict.
We can use the sandbox as the repository for an initial set of tests as well. Given a couple examples, I'll invite a wider audience to come in and propose patches to add coverage to features.
Comment #28
larowlanmtdowling pointed out on twitter that goutte which uses guzzle 3, we're using guzzle 4. I'm working on upgrading goutte to guzzle 4 as part of #2232861: Create BrowserTestBase for web-testing on top of Mink
Comment #29
jessebeach commentedWhat is the smallest step we can take now to allow us to start writing tests?
Could we work grasmash's sandbox into core in an inert way that developer's can leverage locally? This would allow us to start populating core modules with feature tests even though they won't be run on testbot. Then, as the Mink work matures, we can swap that in and hook up with testbot (/me waves wand).
The lionshare of the work will be writing feature tests and the sooner we can start with this work, the more coverage we'll have when we finally run this on the integration level.
Comment #30
catchWith simpletest, we moved the contributed modules and it's tests (some of which had code comments in Polish etc.) directly into core wholesale.
Many of the tests were failing, or were broken by changes to core after they were added. Also there was no testbot support (at least patch-level testing) for some time between the core move and enabling it.
I'd personally be fine with doing similar here, but with one caveat:
Once it's feasible to enable test bot support for behat, we should do so. This means we need to be able to have 100% passing tests when that happens. A small set of passing tests that we can report back to issues when we break them, is a lot better than a large set of failing tests that we can't report on. Also trying to fix issues without automated marking of patches CNW is a losing battle given the rate of core commits, and it's worse the more tests there are. If we have lots of coverage that's OK, as long as we can easily disable failing tests.
On the Drupal driver. I personally would prefer to use REST and fixture sharing if we can. For one thing this would allow for using the core behat framework to run tests on non-local sites for client projects etc.
However given it works, I think using the Drupal driver for setup only is a good start and we can see how it goes down the line - as long as we don't switch between the drupal driver and mink back and forth it shouldn't be an issue with assertions.
Comment #31
jessebeach commentedAfter some discussion with catch, I think it's necessary to define the goals here:
1. Replace simpletest with Behat/(Mink|Goutte)
2. Use Behat + ?? for JavaScript Unit Tests
3. Use Behat + Selenium (or some other JS enabled extension) for JavaScript feature tests
Given that Simpletest works right now, replacing it is less of a concern compared to the zero coverage we have for JavaScript in core.
So, when I mentioned before, what is the smallest step we can take to start writing tests, I meant feature and unit tests for JavaScript. It's my understanding that grasmash's work in the sandbox will allow us to start writing feature tests for JavaScript.
My concern is that this work not conflict with larowlan's efforts to replace simpletest with a Behat/Mink combo.
Comment #32
larowlanThe approaches are compatible.
Regardless, I'm blocked since we went to guzzle 4. You might be in a similar boat with the goutte behat driver.
See https://github.com/fabpot/Goutte/pull/140
Comment #33
berdirBehat with Mink/Goutte is working fairly well with @larowlan's goutte port, my mink goutte driver port (linked above) and a bunch of additional patches and hacks. You can even configure your composer.json file to pick up our ports automatically like this:
(We have that in a module and use the composer_manager module to pick it up)
A few pieces are not yet available, the mink-extension package also needs some changes, haven't figured out what to do with that as it's an old version.
Comment #34
grasmash commentedI've updated my sandbox, which is now functional. I've also added a screencast that provides a walkthrough of the changes and instructions for running the behat tests locally.
@Berdir @larowlan I have not encountered any issues with Guzzle 4 as of yet. However, I'm open to utilizing the Mink/Goutte port.
Comment #35
grasmash commentedMosche pointed out that this approach adds a new requirement that the core directory be writable at install, which nobody (myself included) wants. A couple of alternative:
I've made a branch called no-install-step, which implements approach #2. However, I'm not certain which option is better. A quick comparison (please add your thoughts):
Keeping behat.yml in /core:
Pros:
Cons:
Moving behat.yml to sites/default
Pros:
Cons:
Comment #36
pbuyle commentedNote: The following is a copy/paste with liugh edit of comment #158 in #237566: Automated JavaScript unit testing framework as requested by @nod_.
Unit testing, integration testing and validation testing testing are three different beasts, looking for a single solution for all three of them is doomed to failure (or at least ugly hack and workarounds the limitations of the choosen tool in order to use it iun a way it wasn't designed for).
QUnit is a unit testing framework for JavaScript, like PHPUnit is for PHP. So if what is needed are integration and validation tests, something more than QUnit is indeed needed. IMHO, for unit testing in JS, neither a browser or an HTML page are required, but you may need to mock some DOM objects (ie. you don't run your tests over an actual site with real pages). For instance, a properly designed Drupal behavior should be testable by calling it over a set of fixture DOM elements (ie.
contextof the behavior) and asserting the wanted changes of these elements or their children.Being a BDD framework, Behat is a more a validation testing framework. It tests an complete web application as a blackbox, not its individual components. So it could be used to validate that the JavaScript on a standard Drupal install works as expected. As a bonus, Behat is also usable to test behaviors defined by both PHP and JavaScript at the same time. An example of validation testing would be testing that a specific Views admin scenario create the expected view.
That leave us with integration testing, which is hard to implement over code that is not designed as loosely coupled components. Unit testing has the same kind of issue, but while it is still possible to unit test individual functions and classes by mocking their (hidden) dependencies, integration testing requires a known logic to assemble components together in order to be able to tests the various integration scenarios.
My understanding is that event in D8, Drupal's JavaScript code is not designed as components (even tightly coupled), making integration testing nearly impossible to implement. So focus on both unit testing (which the original issue #237566 was all about) and validation testing (which seems to be to point of this issue) will be more rewarding. Both will encourage more discipline and better quality in the JavaScript code, which should eventually make it possible to implement integration testing.
Comment #37
pbuyle commentedGiven my comment in #36, the idea of using "Behat + ??" from @jessebeach in #31 for unit testing is, IMHO, a bad one. Even if using Behat for unit testing does not create issues, it will continue to blut the line between the three kind of testing and fail to encourage developer to design code with lously coupled component.
Comment #38
sun@mongolito404: Well said. Nice summary on concepts. We might want to consider to incorporate that almost literally into core API docs.
Comment #39
larowlanBecause we went guzzle4 looks like we might need to use behat 3. Which will mean refactoring.
https://github.com/Behat/MinkGoutteDriver/pull/34#issuecomment-41444679See
Comment #40
fgmFWIW, here is the temporary location for the Behat 3 docs, until the main site is updated to cover Behat 3 instead of 2.5: http://behat.readthedocs.org/en/latest/index.html
Comment #41
larowlanNote also http://facebook.github.io/jest/index.html
Comment #42
pbuyle commented@larowlan: Jest is a unit testing framework (which look awesome, if only because it mocks the DOM). This issue is about using Behat for functionnal testing. Unit testing and functionnal testing (which I prefer to name validation testing) are different things, have different needs and are better served by different tools.
Comment #43
larowlan@mongolito404 yes I'm aware but #237566: Automated JavaScript unit testing framework was closed in favour of this, so this is our de-facto place for listing stuff.
Comment #44
benjy commentedAs mentioned here https://drupal.org/node/2232861#comment-8778953
Codeception could be another alternative to Behat.
Comment #45
rcross commented+1 for some review/discussion of codeception as an alternative to Behat.
Comment #46
grasmash commentedHere is a first stab at integrating Behat with Drupal 8 core.
Some notes on the patch:
Some notes on the module:
To test this:
composer update "drupal/drupal-extension"cd core/scripts./run-behat-tests.shComment #47
grasmash commentedUpdating status.
Comment #49
sunDidn't review the patch, but want to raise early: The files should be located in
./tests/features/*.feature- i.e., within the./testsdirectory of each module and outside of./srcdirectories as those are reserved for PHP code.Comment #50
grasmash commentedResubmitting patch. I've removed views integration for now (since it was causing testbot failures) and I've moved .feature files to tests/features at sun's suggestion.
Unfortunately, a recent change to session handling in D8 core requires a few changes to the drupal-extension library before this can be merged. We'll need to wait for 1.0.3. This commit will fix it: https://github.com/Berdir/drupalextension/commit/bb7e705c31064d616421949...
Comment #51
grasmash commentedAaaand I'm attaching the patch.
Comment #53
grasmash commentedWell, 16 failures errors is better than 61!
The following error occurs due to the fact that I haven't actually committed the new library, just added it to composer.json.
Class 'Behat\Gherkin\Keywords\ArrayKeywords' not foundThis may be causing the module enable to fail, therefore triggering more test failures.
What's the proper procedure for updating composer dependencies in core patches?
Comment #54
nod_You need a dedicated issue for adding the lib so that Dries can review and commit.
Comment #55
grasmash commented@nod_ Created #2302545: Add Behat libraries to D8 core
Comment #56
grasmash commentedComment #57
dave reidCurious if we'd be able to use something like this to test interactions with more complex JavaScript, like interacting with CKEditor?
Comment #58
dsnopek@Dave Reid: We use Behat to test TinyMCE in the Panopoly test suite. ;-) I think it should be possible to test CKEditor as well!
Comment #59
xjmThis would be huge.
Comment #60
benjy commentedI posted some concerns for discussion with Behat here: https://www.drupal.org/node/2302545#comment-8985123
JS testing would be huge, I agree with that.
Comment #61
pbuyle commented@xjm: The title is misleading now. Behat is not restricted to JavaScript testing and is not a generic solution for JavaScrip testing (for instance, Behat is not the appropriate tools for JavaScript unit testing). Also, Behat can be used to test the result of PHP, and even more importantly, to test the integration of JavaScript and PHP code. See my comment in #36.
IMHO, if Behat is to be used (which would be great), it should not be discussed and designed as a JavaScript testing solution.
Comment #62
nod_Indeed using behat had a nice side effect of allowing us to test JS but it wasn't restricted to it as the related issues show.
I guess the issue summary should be updated.
Comment #63
moshe weitzman commentedRetitle based on #36. We will test both PHP and javascript code to verify that it accomplishes its goals at a high level.
I hope to reroll this patch soon.
Comment #64
scor commentedI had to update drupal/drupal-extension to get a working install of behat, a fix a few things in the patch. I'm attaching a reroll here.
Comment #66
clemens.tolboomI assumed this was about Behat 3? What is the reason to use Behat 2 instead of Behat 3?
Reading https://github.com/jhedstrom/drupalextension
As Behat 3.0.0 is out since 2014-04-20 shouldn't we use it? Behat 2 latest isn't touched since 2014-04-26.
Comment #67
kostajh commentedI came to this issue via #237566: Automated JavaScript unit testing framework. I'd like to know if there is any interest in using CasperJS instead of Behat for front end testing. In my experience, CasperJS is a much better tool than Behat (at least the 2.x version) for testing JavaScript interactions, and is also a lot faster than Behat. It's easy to install and learn. It doesn't have a Gherkin style syntax for writing scenarios but this is somewhat mitigated by adding comments at the top of each test file explaining what is happening.
Drush integration is also possible for CasperJS.
I'd be happy to provide proof-of-concept code, and work to get this implemented, if there is interest.
Comment #68
attiks commentedA benefit of using mink/behat is that you can do more than just frontend testing, you can control the back end using the api.
Another benefit us that it can control a lot of browsers.
Comment #69
kostajh commented@attiks CasperJS can interact with the backend via Drush, which I think would be sufficient for this scope. It can also drive WebKit (via PhantomJS) or Gecko (using SlimerJS), which I also believe would be sufficient for what we are discussing here.
Comment #70
attiks commented##6 I know CasperJs, but it is limited to those 2 browsers, and I hope that once we have this system for core, we will use it to test on as much browsers as possible.
There are/were to many javascript bugs in Drupal 7, most only showing on some combo of browser and OS. Since Drupal 8 contains even more javascript we (developers as well as users/end users) can only benefit of advanced front end and integration testing.
You're right about the unit testing part, we need to handle that as well, but there are other tools that we can use.
PS: We use a combination of jenkins, behat and phantomjs to do automated frontend testing.
Comment #71
kostajh commented@attiks that's a very good point and this alone probably outweighs the benefits of using CasperJS.
Comment #72
pbuyle commented@kostajh Please see #36, #61 and #63, Behat usage is not for considered for JavaScript unit testing (as reflected in the issue title).
Comment #73
roysegall commentedWell.. I don't know what the status of this issue but i have something that may help this issue - https://github.com/roysegall/behat.
Comment #74
chx commentedWhat happened to #44 and #45 mentioning codeception? See http://codeception.com/docs/01-Introduction . Although it's still PHPunit :( but it's PIE. Also, should I repost here my concerns over the whole testing world becoming phpunit based from #2469731-5: Document when to use BrowserTestBase or is linking enough or what's the best place to talk about this?
Comment #75
pfrenssen#2469731: Document when to use BrowserTestBase is probably sufficient for now, we don't need to discuss this in two issues.
Comment #76
chx commented@pfrenssen do you see any replies to those concerns there? I don't.
Comment #77
m1r1k commentedHere is rerolled patch with DrupalExtension 3.x (because obviously 1.x is outdated and pretty limited to huge projects when separate independent contexts are required)
Comment #79
m1r1k commentedAll errors are missed library related, should I add libraries to the repo to check tests?
Comment #80
clemens.tolboomNo newline at end of file
Whitespace
Comment #81
m1r1k commentedComment #82
yannickooJust a quick question to the patch developers:
Which function do you prefer to get the path to the module? In the patch are two functions used:
\Drupal::moduleHandler()->getModule('behat')->getPath()and the good olddrupal_get_path('module', 'behat')Comment #83
jhedstromBehat has it's own command-line utility (similar to PHPUnit), so I'm not sure why we'd need to add and maintain a module that provides a UI. I think it would make more sense to keep the
behat.yml.distfile in a similar location tophpunit.xml, and the tests under thecore/tests/featuresdirectory (and in modules,MODULE/tests/features).Comment #84
xanoAgreed. We've had numerous problems with the Simpletest UI already, especially in combination with PHPUnit. If we discover we need additions to the third party (command-line) tools we use, we should try to fix those upstream instead.
Comment #85
yannickooBTW #2232861: Create BrowserTestBase for web-testing on top of Mink is fixed now!
Comment #86
dawehnerFor now the this a reroll, but I think we should refocus on the longrun. More tomorrow ...
Comment #88
clemens.tolboomThe $base_url is set above in the $behat_conf.
So what's the message about?
I don't understand this
'Grant all permission for behat'
It does not reflect the purpose for administer Behat.
Behat should be uppercase.
No new line
Where is behat.api.php describing hook_behat_info()?
Are we using Behat 2 syntax? /^ and $/ are iirc Behat 2 syntax.
Whitespace
Comment #89
phenaproximaI concur with @jhedstrom and @Xano in #83 and #84. I don't see the need for a UI, except to maybe configure behat.yml and the environment since that can vary. But even that might best be packaged as a Drush command or something.
Comment #90
dawehnerI totally agree, just wanted to reroll so people can attention more.
Regarding behat, I think it should just work like any other behat usage, so using the behat binary ideally.
Comment #91
phenaproximaI took a quick look through the patch and found some relatively minor issues and nitpicks. I'm sure there are larger issues to deal with but my head is not far enough into this to raise any major objections :)
I thought DRUPAL_ROOT was deprecated/replaced by the app.root container parameter?
This looks like it can go in a static .permissions.yml file.
D'oh. :)
s/behat api/Behat API
Nit: Can be one line.
Wat? This seems odd to me -- a function to register a module and its scenarios will deregister scenarios? Maybe this should be removed, or at least commented better.
Can be a single line, and ditto with DRUPAL_ROOT no longer being a thing.
Scenario::create($data)->save()
Number of scenarios registered, perhaps? IMO it should throw an exception on failure.
This oughta be using DBTNG's fluent syntax (or better yet, an entity query), not db_query().
Ditto.
\Drupal::entityManager()->getStorage('behat_scenario')->delete($scenario_registrations)
Nit: Can be one line.
I don't like that this function returns a boolean to indicate failure. IMO, failure to set the environment correctly is a severe enough problem that an exception should be thrown.
Why is this commented out? A @todo comment may be a good idea :)
Scenario::loadMultiple()
s/scenario/scenarios
Nit: There's an extra line here.
Nit: s/id/ID
s/behat/Behat
Why do we need this?
Storage handler, not controller class.
I thought it was unkosher to add extra stuff after an @inheritdoc?
I could be wrong, but IIRC aren't most if not all of these step definitions rendered unnecessary by MinkContext and DrupalContext?
Nit: Extra line.
The blank line has extra white space.
Presumably (hopefully) this could eventually be merged into run-tests.sh or whatever.
Comment #92
claudiu.cristea#88.1: Fixed. Added also translation for that string and alternative message if the behat.yml writing fails.
#88.2: Fixed and moved to
behat.permissions.yml#88.3: Fixed.
#88.4: Seems that the discovery is not based on that hook. Removed the reference.
#88.5: Don't know. Not addressed.
#88.6: Fixed.
Removed.
Are we gonna expose and handle scenarios on UI?
EDIT: And I think behat.inc should be moved to a manager class.
Comment #95
dawehnerI think we first should think about what we actually want ... rolling a patch was a bad idea probably.
Do we really want the UI? I think absolutely no. IMHO you don't get any advantage out of having one, or do you?
Comment #96
claudiu.cristeaI agree. In #92 I removed the links from the entity. There's only the settings UI left.
Comment #97
phenaproximaI'm a bit late jumping into this issue, but I'm opposed to having a UI for Behat. It's not a direction I think we should be going, given the way core in which core is already using PHPUnit and moving away from SimpleTest. Behat is already very usable from the command line, and bolting on a UI would add complexity that provides no advantage to core developers. With Behat itself in core (along with the Mink and Drupal extensions), a UI is the kind of thing that would be well-suited to contrib. But it's not something core developers should spend time on.
Just my $0.02.
Comment #98
claudiu.cristeaFixed almost all from #91
Comment #100
benjy commentedThe issue summary references an offline conversion saying, lets use Behat but i'm still yet to see an issue that outlines why that's a good idea. Are we doing Story BDD now? The IS mentions that "lots" of core developers know/use Behat, that may be true but it's still a subset of core developers who know PHP, so we're making testing less accessible to our newcomers.
It seems people want to test JS, and that's great but we can test our JS enabled code by writing PHP tests via BrowserTestBase and using whichever browser plugin we want. We don't need and we shouldn't use Gherkin unless we have a need.
This just makes me cringe. Behat isn't designed to replace all of what we test with ST. BrowserTestBase is as far as we needed to go. I think we need Mink, not Behat. http://elnur.pro/behat-and-mink-are-not-meant-to-be-together/
Comment #101
elachlan commentedComment #102
cosmicdreams commented@benjy in #100:
After reading your comment I followed your link and that started a journey through a lot of blog posts that talk about the intent of Behat, it's proper place within a project, and alternative strategies of testing that do not use Behat.
From those discussions I've gathered a few key points:
All that said:
I still see the value of using Behat for testing Drupal. Because:
So imagine this:
Road #1: We include Mink but not Behat. We write all the tests we need in order to cover all of Drupal's frontend and javascript using a combination of PHPUnit and Mink (and drivers).
Benefits:
For all the people who are writing PHPUnit tests now, a consistent platform, confidence, and speed of development as they create tests to cover JavaScript behaviors.
We eventually convert all the Simpletest tests to PHPUnit.
Perhaps we eventually create objects to make it "easy" to write these kind of frontend tests. (that sounds like us)
In the end, we'll have one test framework to cover all the kinds of tests in Drupal.
Detriments:
You have to know PHPUnit to participate.
You have to be comfortable with code and the level of complexity that exists in our tests to make progress.
Road #2: We continue to expand PHPUnit's coverage to Unit testing, functional testing, and integration testing. We also use Behat to cover all the user stories of Drupal.
Benefits:
We document all of Drupal's user stories
We have a great reference for how to turn user stories into tests for other Drupal projects
We continue to benefit from PHPUnit's tests, it continues to be the principal source of truth on whether something has complete test coverage or not.
Detriments:
We now have two tests frameworks to maintain
We'll need people to write the Behat tests, who may not be the same people who write the PHPUnit tests
Therefore the tests may get into conflict (but we can make sure they don't. We're not robots)
So that's my whole thought about this. I see the value of going through the exercise of coverage the business rules with Behat tests. So we can better communicate about minutia of it's functionality. I also see the benefit of converting our functional tests into PHPUnit tests (not Behat). I'm interested in everyone else's thoughts.
Comment #103
larowlanThanks @cosmicdreams.
Fwiw we're already well down road 1, BrowserTestBase has been in for some time and JavaScriptTestBase is close.
Comment #104
benjy commented@cosmicdreams, glad you found some of those posts interesting, I think as larowlan already mentions, JavaScriptTestBase is the way forward.
Comment #105
dawehnerMaybe this might help people to be confused less about what currently we try to achieve:
The current testing plan
Drupal iterated on the great success of simpletest in Drupal 7 to improve the following points:
a) Enlarge the test coverage
b) Improve the test developer experience
Therefore we now have a 3 level testing system:
1. Unit tests
Unit tests are there only for testing a particular component, like a class. Those
are tests using PHPUnit's
\PHPUnit_Framework_TestCase2. API tests
In order to test the complexity of Drupal its not enough to test each individual
component but you also need to test the ingration between various subsystems on sort
of a working Drupal. The kernel test set ups a bare running minimal Drupal, which
allows you to call APIs, but not to visit the actual site.
In order to write those you need to extend
KernelTestBase.There is an old one and a one new. I would recommend the new one (
\Drupal\KernelTests\KernelTestBase3. Integration/Functional tests
One level higher you want to browse the actual site and check whether the behaviour is
as expected. This field is currently still in the flux.
There is
\Drupal\simpletest\WebTestBasewhich is a safe choise based upon simpletest. We try to replace that slowly over time by\Drupal\simpletest\BrowserTestBasewhich uses a browser abstraction library called Mink.This would allow us to not only use a PHP based "browser" like WebTestBase does, but one day use an actual browser or PhantomJS as browser, so we can test javascript behaviour as well. This is researched on #2469713: Step 2: Create a JavaScriptTestBase using PhantomJs Driver/Binary.
4. BDD
On an even higher level we should document what Drupal does. Using a Business readable DSL allows us to document it in a implementation agnostic way.
Doing that using Behat would allow us to execute that behaviour documentation as well, though its not a replacement for any of the previous levels, rather a supplement.
In case we have clear levels on the code architecture site of things, it also becomes easier to understand on which level you want to target your tests on.
Comment #106
cosmicdreams commentedThis seems like this should be documented somewhere.
If tests have this natural categorization could we make it easy for developers to know what kind of test they're looking at / organize tests into folders / annotate tests so that their purpose / job is well known?
Comment #107
benjy commentedI think BDD/Behat often become interchangeable but to clarify BDD isn't 1 level higher than functional tests. BDD is just a way of testing, often using Ubiquitous Language to drive the tests. You can just as easily use SpecBDD to unit test object behaviour.
However, I think what you were suggesting is that we use Behat and in-turn StoryBDD to provide a high level description on the features in Drupal, +1 to that.
Comment #108
dawehnerYeah I see your point, this is right. SpecBDD indeed can be used as an alternative of unit testing. I think though at least for now we should try to limit the options in core, given there are already quite a lot of them
Comment #109
clemens.tolboomGuess we can move this safely to 8.2.x
In trying to answer @cosmicdreams visiting https://www.drupal.org/documentation gives no clue.
- We do have https://www.drupal.org/phpunit (level 1)
- Searching on https://www.drupal.org/search/site/webtest?f[0]=ss_meta_type%3Adocumenta... gives API docs :-(
- https://www.drupal.org/project/behat_testing
@dawehner where can we put your #105 ?
Comment #110
nevergoneThis is interesting issue. Possible Drupal 8.2.0?
Comment #111
pbuyle commentedBDD is actually not just a way of testing, BDD is a software development process. Using tools designed for BDD to just execute some tests is not BDD. Off course, you can use BDD tools anyway you want. There is nothing stopping you from using an icecream truck as moving truck when changing apartment, but it's not really designed for that and you shouldn't call that selling icecreams.
Comment #112
dawehnerCan't agree more with that statement.
Comment #113
dawehnerHere is a document a couple of people have been working on to clarify what behat is about and what it is not: https://docs.google.com/document/d/17raktxD51MP0WUvqtNQFsCzevYgDNkvl7jOu...
Comment #114
catchYes I think we have plenty with phpunit + mink and should leave behat/gherkin/BDD for now.
That could be revisited, but we really need to bring our existing tests up-to-date and rationalise them first. So postponing this for now on #2735005: Convert all Simpletest web tests to BrowserTestBase (or UnitTestBase/KernelTestBase) (but really on further follow-up once the initial conversions are done).
Comment #115
dawehnerIt could be interesting to use gherkin as a pure language to describe features we want to add to core, but skip the testing aspect of it.
This helps already to do less bikeshedding once we are on the implementation level.
Comment #116
pwolanin commentedYes, I think it would be great to start using Gherkin as a standard format for describing features and user interactions, which we could leverage in the future for testing if appropriate.
Comment #117
cosmicdreams commentedThat makes sense if you look at Gherkin / Behat as a communication tool
Comment #119
gábor hojtsyMoving to core ideas as a plan.
Comment #120
yoroy commentedWhat's the latest thinking around this? Is there another active thread for this somewhere maybe?
Comment #121
dawehnerI think everyone involved in the phpunit initiative doesn't believe in behat as a testing tool for Drupal.
Behat is a tool to talk to enable a common business language with your client for your thing you are building. You can then validate this business language by converting these constrains into running code.
What Behat does't solve is to provide full test coverage for the full complexity of the world. Writing the step definitions is not easy to maintain and you end up writing basically a lot of code, so you could just write code only tests in the first place. For example having context is a really tricky topic in behat.
On top of that I think having edge case testing is really hard in Behat, given that you again need to define a lot of custom step definitions to be handle to deal with them, which ends up in a maintenance nightmare. This is much less of a problem for client projects / products, because you have way more limits involved. You have concrete and endless usecases, while in core we just enable people to build things with our work.
Don't get me wrong, I personally believe that the business language aspect of Behat/Gherkin/BDD is great and super useful! I could imagine having something along the lines of userstories expressed in issues to describe bugs, features wishes etc. would be beneficial, but I don't believe that converting those into runnable code would fit for the complexity of Drupal.
Comment #122
berdir+1.
Behat is great for actual projects, to test the integration of all the modules you use, their configuration, the specific case you chose to use them in your project and a limited amount of test scenarios.
But it's not well suited to do the kind of tests we have to do in Core, with many variations, very specific assertions and lots of API calls and so on.
At best, it could be used to test the new example install profile that we want to put in core, as that basically is a specific project. But I think it would be a lot of dependencies for just that and doing those tests isn't that much harder to do directly against Mink. A few years ago, when this was started, we didn't have that. Now we have browser and Javascript tests through Mink.
I think we can close this.
Comment #123
benjy commentedWell put dawehner. +1 to close this issue.
Comment #124
ptmkenny commentedI like @Berdir's suggestion that the example install profile include Behat tests.
Such tests may not be necessary to ensure the install profile functions correctly, but one of the great things about Drupal is that you can get started without knowing how to code, and learn to code later. Behat is a way to do the same thing with testing for the site you are building, but Behat documentation isn't very good for people who are just trying to write a couple scenarios for the first time, so having good, working examples for a standard Drupal install profile (a way to check "Did I break anything?") is a great way to help people who are getting started with Drupal help themselves debug problems.
Comment #125
mlncn commentedNow that we have a fantastic installation profile in core, shall we revisit, as suggested by Berdir, the advantages of getting Behavior-Driven Development tests in core mentioned in this thread?
* document Drupal's user stories— high level descriptions of the features in Drupal (and/or Umami) (cosmicdreams / Benjy)
* have a great reference for how to turn user stories into tests for other Drupal projects (cosmicdreams / ptmkenny)
The Drupal 8 testing documentation mentions Behat as an addition to the three kinds of tests in D8 core. We're clear on not trying to replace any of those tests, but adding human-readable subject matter tests that can also be run.
The first step would be to write these high-level business-logic acceptance tests— a virtue in their own write (per dawehner).
Perhaps a good place to start would be the Umami user stories (not certain that's the final or most complete list).
Later we can handle wiring up the human-readable gherkin to tests which can be automated, and work out if or how to break up Behat features (collections of scenarios) among installation profiles and modules or feature modules.
Comment #126
cosmicdreams commentedSo as a first step, to clarify, you're thinking we should ensure that the spreadsheet you listed is really the complete list of user stories for hte Umami installation profile?
I think it would also be pointed out that what we're not saying should be done at this time is making the running of behat tests a requirement of the testbot. That we're just asking for the inclusion of the behat tests so that it can be provided to developers as a complete example of how one would write behat tests for an installation profile. Like, a demonstration of the level of effort it takes to both provide and maintain the tests.
Is that right?
Comment #127
cosmicdreams commentedOr,
If not specifically Behat, a suite of functional tests that cover every user story.
Comment #128
nod_We have a way to test JS now, it's getting used by olivero/claro and the new things we develop.
I don't think this is relevant anymore.