kevin1024 / vcrpy

Automatically mock your HTTP interactions to simplify and speed up testing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Problem with failing test while django's unittests and using --parallel

jedie opened this issue · comments

I didn't use pytest. Just normal unittests and Django's test runner, that implement --parallel that used multiprocessing.pool.Pool ...

On CannotOverwriteExistingCassetteException errors i get "cannot pickle" error like:

test_change_product_categories (FooBarTestCase) failed:

    CannotOverwriteExistingCassetteException("Can't overwrite existing
    cassette (PosixPath('.../foobar.vcr.yaml')) in your
    current record mode ('none').\nNo match for the request (<Request
    (POST) https://api.foobar.com/b2c_local/graphql>) was
    found.\nNo similar requests, that have not been played, found.")

Unfortunately, the exception it raised cannot be pickled, making it impossible
for the parallel test runner to handle it cleanly.

Here's the error encountered while trying to pickle the exception:

    TypeError("cannot pickle 'module' object")

You should re-run this test with the --parallel=1 option to reproduce the
failure and get a correct traceback.

I get a normal traceback running the tests without --parallel ;)
Think CannotOverwriteExistingCassetteException can't be pickle, isn't it?

Version info:

  • Python 3.10
  • VCR.py v4.3.1
  • Django v4.1.9

This should work:

pip install tblib

https://code.djangoproject.com/ticket/25497

No, tblib v1.7.0 is already installed ;)

@jedie similar to #710 this will likely need a minimal reproducible example in code to be worked on.

Is this about CannotOverwriteExistingCassetteException not being pickable or about CannotOverwriteExistingCassetteException being thrown in the first place?

@jedie did you see my reply at #711 (comment) ?

I had another look just now, starting with an empty Django project, adding two simple VCR.py tests and using record_mode=RecordMode.NONE as seen in the error output above. Also I checked the documentation of record mode "none". My current impression is that:

  • Record mode none was supposed to throw an exception on new requests as documented.
  • Record mode none controls property Cassette.write_protected.
  • Exception CannotOverwriteExistingCassetteException may be misleading because there is no cassette file at that moment. Could potentially be improved, but a change like that may be considered a break in API.
  • Use of ./manage.py test --parallel=2 did not get me the errors that @jedie mentioned above, so I cannot reproduce it.

If someone would like to reproduce what I did, it's this:

# cd "$(mktemp -d)"
# python3.10 -m venv venv
# source venv/bin/activate
# pip3 install vcrpy django
# django-admin startproject issue711
# cat issue711/issue711/test_issue711.py  # hand-made file
from unittest import TestCase
import urllib.request

from vcr import VCR
from vcr.record_mode import RecordMode


class TestOneTwo(TestCase):
    def test_record__none__one(self):
        with VCR(record_mode=RecordMode.NONE).use_cassette('one.yaml'):
            response = urllib.request.urlopen('http://www.iana.org/domains/reserved').read()
            assert b'Example domains' in response
            
    def test_record__none__two(self):
        with VCR(record_mode=RecordMode.NONE).use_cassette('two.yaml'):
            response = urllib.request.urlopen('http://www.iana.org/domains/reserved').read()
            assert b'Example domains' in response
# ( cd issue711/ && ./manage.py test --parallel=2 -v2 )
Found 2 test(s).
Skipping setup of unused database(s): default.
System check identified no issues (0 silenced).
test_record__none__one (issue711.test_issue711.TestOneTwo) ... ERROR
test_record__none__two (issue711.test_issue711.TestOneTwo) ... ERROR

======================================================================
ERROR: test_record__none__one (issue711.test_issue711.TestOneTwo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/tmp.vt6waYAV1L/issue711/issue711/test_issue711.py", line 11, in test_record__none__one
    response = urllib.request.urlopen('http://www.iana.org/domains/reserved').read()
  File "/usr/lib/python3.10/urllib/request.py", line 216, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.10/urllib/request.py", line 519, in open
    response = self._open(req, data)
  File "/usr/lib/python3.10/urllib/request.py", line 536, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/usr/lib/python3.10/urllib/request.py", line 496, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.10/urllib/request.py", line 1377, in http_open
    return self.do_open(http.client.HTTPConnection, req)
  File "/usr/lib/python3.10/urllib/request.py", line 1352, in do_open
    r = h.getresponse()
  File "/tmp/tmp.vt6waYAV1L/venv/lib/python3.10/site-packages/vcr/stubs/__init__.py", line 253, in getresponse
    raise CannotOverwriteExistingCassetteException(
vcr.errors.CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('one.yaml') in your current record mode (<RecordMode.NONE: 'none'>).
No match for the request (<Request (GET) http://www.iana.org/domains/reserved>) was found.
No similar requests, that have not been played, found.

======================================================================
ERROR: test_record__none__two (issue711.test_issue711.TestOneTwo)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/tmp/tmp.vt6waYAV1L/issue711/issue711/test_issue711.py", line 16, in test_record__none__two
    response = urllib.request.urlopen('http://www.iana.org/domains/reserved').read()
  File "/usr/lib/python3.10/urllib/request.py", line 216, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/lib/python3.10/urllib/request.py", line 519, in open
    response = self._open(req, data)
  File "/usr/lib/python3.10/urllib/request.py", line 536, in _open
    result = self._call_chain(self.handle_open, protocol, protocol +
  File "/usr/lib/python3.10/urllib/request.py", line 496, in _call_chain
    result = func(*args)
  File "/usr/lib/python3.10/urllib/request.py", line 1377, in http_open
    return self.do_open(http.client.HTTPConnection, req)
  File "/usr/lib/python3.10/urllib/request.py", line 1352, in do_open
    r = h.getresponse()
  File "/tmp/tmp.vt6waYAV1L/venv/lib/python3.10/site-packages/vcr/stubs/__init__.py", line 253, in getresponse
    raise CannotOverwriteExistingCassetteException(
vcr.errors.CannotOverwriteExistingCassetteException: Can't overwrite existing cassette ('two.yaml') in your current record mode (<RecordMode.NONE: 'none'>).
No match for the request (<Request (GET) http://www.iana.org/domains/reserved>) was found.
No similar requests, that have not been played, found.

----------------------------------------------------------------------
Ran 2 tests in 0.008s

FAILED (errors=2)

Unless someone else posts something producible, I'll close this issue as "cannot reproduce" in a few days.

@jedie please note that in general detail level and a reproducer like this will be expected for future bug reports to VCR.py if any. Thanks!

Closing for lack of a reply and minimal reproducer. Happy to re-open if someone can provide a minimal reproducer. Closing…