Opened 5 years ago

Closed 5 years ago

#30089 closed Bug (invalid)

TestClient doesn't accept data with duplicate keys (SELECT multiple)

Reported by: Adam Gilman Owned by: nobody
Component: Testing framework Version: dev
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Adam Gilman)

When constructing tests for forms with SELECT elements which allow multiple item selection, the test client doesn't accept multiple selections due to the fact it uses dict internally and results in a squashed single key

Failing test

def test_post_multi_select(self):
        "POST SELECT multiple data to a view"
        post_data = QueryDict(mutable=True)
        post_data.update({'value':37})
        post_data.update({'value':38})
        response = self.client.post('/post_view/', post_data)

        # Check some response details
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.context['data'], ['37', '38'])
        self.assertEqual(response.templates[0].name, 'POST Template')
        self.assertContains(response, 'Data received')

*updated

Change History (10)

comment:1 by Adam Gilman, 5 years ago

Easy pickings: unset

comment:2 by Simon Charette, 5 years ago

Resolution: invalid
Status: newclosed

It looks like you have a bug in your reported test case, you are updating post_data twice with {'value':37} and never including 38.

Please re-open if you reproduce with .update({'value':38}).

comment:3 by Adam Gilman, 5 years ago

Apologies, typo in my original test. Good catch. Updated test in description and failure below:

FAIL: test_post_multi_select (test_client.tests.ClientTest)
POST SELECT multiple data to a view
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/dev2/.pyenv/versions/3.7.0/lib/python3.7/unittest/case.py", line 59, in testPartExecutor
    yield
  File "/Users/dev2/.pyenv/versions/3.7.0/lib/python3.7/unittest/case.py", line 615, in run
    testMethod()
  File "/Users/dev2/Documents/GitHub/django/tests/test_client/tests.py", line 113, in test_post_multi_select
    self.assertEqual(response.context['data'], ['37', '38'])
  File "/Users/dev2/.pyenv/versions/3.7.0/lib/python3.7/unittest/case.py", line 839, in assertEqual
    assertion_func(first, second, msg=msg)
  File "/Users/dev2/.pyenv/versions/3.7.0/lib/python3.7/unittest/case.py", line 832, in _baseAssertEqual
    raise self.failureException(msg)
AssertionError: '38' != ['37', '38']
Last edited 5 years ago by Tim Graham (previous) (diff)

comment:4 by Adam Gilman, 5 years ago

Resolution: invalid
Status: closednew

comment:5 by Adam Gilman, 5 years ago

Description: modified (diff)

comment:6 by Carlton Gibson, 5 years ago

I'm not sure the test is right here.

post_view isn't using getlist(), so even if POST is a QueryDict, we'll only get the single value...

            c = Context({'data': request.POST['value']})
Last edited 5 years ago by Carlton Gibson (previous) (diff)

comment:7 by Carlton Gibson, 5 years ago

Triage Stage: UnreviewedAccepted
Type: UncategorizedBug
Version: 2.1master

But this fails:

        post_data = QueryDict(mutable=True)
        post_data.update({'value':37})
        post_data.update({'value':38})
        self.assertEqual(post_data.getlist('value'), [37, 38])
        request = RequestFactory().post('/post_view/', post_data)
        self.assertEqual(request.POST.getlist('value'), ['37', '38'])
   self.assertEqual(request.POST.getlist('value'), ['37', '38'])
AssertionError: Lists differ: ['38'] != ['37', '38']

So this looks valid.

in reply to:  7 comment:8 by Nasir Hussain, 5 years ago

Replying to Carlton Gibson:
request.POST is actual representation of request.body. A post request could have only one parameter of the same name in its body. That's why it returns a single element. I don't think if it's a bug.

comment:9 by Tim Graham, 5 years ago

I didn't look into the cause of the issue but normally a dictionary rather than a QueryDict is used as test client data.

post_data = {'value': [37, 38]} passes the test.

comment:10 by Carlton Gibson, 5 years ago

Resolution: invalid
Status: newclosed
Triage Stage: AcceptedUnreviewed

Then it’s incorrect usage. Good. Thanks both!

Note: See TracTickets for help on using tickets.
Back to Top