Repository: aio-libs/aiohttp

Issue:
Test only asyncio loop by default.
aiohttp uses parametrized `loop` fixture which runs all test suite several times: one for asyncio itself and another ones for uvloop and tokio if they are installed.
It's good for aiohttp testing itself but bad for `pytest-aiohttp` users.
For example test suites for my jobs take about 15 mins, we don't like to double the time (we use uvloop, sure).
We could solve the problem by pushing custom `loop` fixture into our `conftest.py` but it is not obvious and robust solution.

I suggest moving `pytest_configure` from `pytest_plugin.py` into `tests/conftest.py` and using only asyncio loop for tests by default.
As an option we could add support for command line `--aiohttp-loops` option and `aiohttp-loops` in `pytest.ini` for helping people to run their tests on specific asyncio loop implementations.


Discussion:
If you go for this, I would strongly +1 for adding a parameter where you can specify with which loops you want to run and pick only one by default (at least for development).

However for travis builds, I would keep passing tests for all the loops (dunno if that was included already in your intentions)
@argaen  yep, it is my intention.
BTW, would you work share my duty and on PR? 
The code change is not very hard.
Sure can do
After checking, I see that the `--loop` option is already supported with the pytest_plugin. The behavior is the following:

1. If nothing is specified, it picks installed loops.
2. If --loop specified, only picks the specified one (you can specify multiple one separated by comma).

With this I have couple of proposals:

1. Leave current behavior

With this, I think its just a matter of updating the `Makefile` needed commands to just use one loop. From what I've seen: `test`, `vtest`, `cov-dev`. Not so sure about `cov` which ends up using tox.

Then I would leave `cov-ci-no-ext`, `cov-ci-aio-debug`, `cov-ci-run` which are the ones used by travis as they are

2. Change default behavior so by default it always picks one loop (no matter if uvloop or tokio are installed) and if you want to run tests with multiple loops, you have to use the `--loop` option. Ofc this requires updating the commands used by travis to use all loops
I'm talking not about aiohttp test suite (running all available loops is perfectly fine) but changing `pytest-aiohttp` default behavior. Now it shares `loop` fixture with internal `./tests`.
@asvetlov, why not just change the default to just use `pyloop`, then aiohttp  `setup.cfg` can include:

    addopts = --loop all

?

Resolving patch:
diff --git a/aiohttp/pytest_plugin.py b/aiohttp/pytest_plugin.py
--- a/aiohttp/pytest_plugin.py
+++ b/aiohttp/pytest_plugin.py
@@ -30,8 +30,8 @@ def pytest_addoption(parser):
         '--fast', action='store_true', default=False,
         help='run tests faster by disabling extra checks')
     parser.addoption(
-        '--loop', action='append', default=[],
-        help='run tests with specific loop: pyloop, uvloop, tokio')
+        '--loop', action='store', default='pyloop',
+        help='run tests with specific loop: pyloop, uvloop, tokio or all')
     parser.addoption(
         '--enable-loop-debug', action='store_true', default=False,
         help='enable event loop debug mode')
@@ -119,29 +119,19 @@ def pytest_configure(config):
     LOOP_FACTORIES.clear()
     LOOP_FACTORY_IDS.clear()
 
-    if loops:
-        for names in (name.split(',') for name in loops):
-            for name in names:
-                name = name.strip()
-                if name not in factories:
-                    raise ValueError(
-                        "Unknown loop '%s', available loops: %s" % (
-                            name, list(factories.keys())))
-
-                LOOP_FACTORIES.append(factories[name])
-                LOOP_FACTORY_IDS.append(name)
-    else:
-        LOOP_FACTORIES.append(asyncio.new_event_loop)
-        LOOP_FACTORY_IDS.append('pyloop')
-
-        if uvloop is not None:  # pragma: no cover
-            LOOP_FACTORIES.append(uvloop.new_event_loop)
-            LOOP_FACTORY_IDS.append('uvloop')
-
-        if tokio is not None:
-            LOOP_FACTORIES.append(tokio.new_event_loop)
-            LOOP_FACTORY_IDS.append('tokio')
-
+    if loops == 'all':
+        loops = 'pyloop,uvloop?,tokio?'
+
+    for name in loops.split(','):
+        required = not name.endswith('?')
+        name = name.strip(' ?')
+        if name in factories:
+            LOOP_FACTORIES.append(factories[name])
+            LOOP_FACTORY_IDS.append(name)
+        elif required:
+            raise ValueError(
+                "Unknown loop '%s', available loops: %s" % (
+                    name, list(factories.keys())))
     asyncio.set_event_loop(None)
 
 


Test patch: