2
2
import os
3
3
import sys
4
4
5
- from hypothesis import given
6
- from hypothesis import strategies as st
7
5
import pytest
8
6
9
7
from ddtrace import Pin
10
- from ddtrace .contrib .pytest .plugin import _json_encode
11
8
from ddtrace .ext import test
12
9
from tests .utils import TracerTestCase
13
10
@@ -106,11 +103,36 @@ def test_ini(ddspan):
106
103
assert len (spans ) == 1
107
104
108
105
def test_parameterize_case (self ):
109
- """Test parametrize case."""
106
+ """Test parametrize case with simple objects ."""
110
107
py_file = self .testdir .makepyfile (
111
108
"""
112
109
import pytest
113
110
111
+
112
+ @pytest.mark.parametrize('item', [1, 2, 3, 4, pytest.param([1, 2, 3], marks=pytest.mark.skip)])
113
+ class Test1(object):
114
+ def test_1(self, item):
115
+ assert item in {1, 2, 3}
116
+ """
117
+ )
118
+ file_name = os .path .basename (py_file .strpath )
119
+ rec = self .inline_run ("--ddtrace" , file_name )
120
+ rec .assertoutcome (passed = 3 , failed = 1 , skipped = 1 )
121
+ spans = self .pop_spans ()
122
+
123
+ expected_params = [1 , 2 , 3 , 4 , [1 , 2 , 3 ]]
124
+ assert len (spans ) == 5
125
+ for i in range (len (expected_params )):
126
+ extracted_params = json .loads (spans [i ].meta [test .PARAMETERS ])
127
+ assert extracted_params == {"arguments" : {"item" : expected_params [i ]}, "metadata" : {}}
128
+
129
+ def test_parameterize_case_complex_objects (self ):
130
+ """Test parametrize case with complex objects."""
131
+ py_file = self .testdir .makepyfile (
132
+ """
133
+ from mock import MagicMock
134
+ import pytest
135
+
114
136
class A:
115
137
def __init__(self, name, value):
116
138
self.name = name
@@ -119,19 +141,19 @@ def __init__(self, name, value):
119
141
def item_param():
120
142
return 42
121
143
144
+ circular_reference = A("circular_reference", A("child", None))
145
+ circular_reference.value.value = circular_reference
146
+
122
147
@pytest.mark.parametrize(
123
- 'item',
124
- [
125
- 1,
126
- 2,
127
- 3,
128
- 4,
129
- pytest.param(A("test_name", "value"), marks=pytest.mark.skip),
130
- pytest.param(A("test_name", A("inner_name", "value")), marks=pytest.mark.skip),
131
- pytest.param({"a": A("test_name", "value"), "b": [1, 2, 3]}, marks=pytest.mark.skip),
132
- pytest.param([1, 2, 3], marks=pytest.mark.skip),
133
- pytest.param(item_param, marks=pytest.mark.skip)
134
- ]
148
+ 'item',
149
+ [
150
+ pytest.param(A("test_name", "value"), marks=pytest.mark.skip),
151
+ pytest.param(A("test_name", A("inner_name", "value")), marks=pytest.mark.skip),
152
+ pytest.param(item_param, marks=pytest.mark.skip),
153
+ pytest.param({"a": A("test_name", "value"), "b": [1, 2, 3]}, marks=pytest.mark.skip),
154
+ pytest.param(MagicMock(value=MagicMock()), marks=pytest.mark.skip),
155
+ pytest.param(circular_reference, marks=pytest.mark.skip),
156
+ ]
135
157
)
136
158
class Test1(object):
137
159
def test_1(self, item):
@@ -140,24 +162,22 @@ def test_1(self, item):
140
162
)
141
163
file_name = os .path .basename (py_file .strpath )
142
164
rec = self .inline_run ("--ddtrace" , file_name )
143
- rec .assertoutcome (passed = 3 , failed = 1 , skipped = 5 )
165
+ rec .assertoutcome (skipped = 6 )
144
166
spans = self .pop_spans ()
145
167
146
- expected_params = [
147
- 1 ,
148
- 2 ,
149
- 3 ,
150
- 4 ,
151
- { "name" : "test_name" , "value" : "value" } ,
152
- { "name " : "test_name" , "value" : { "name" : "inner_name" , "value" : "value" }} ,
153
- { "a" : { "name" : "test_name" , "value" : "value" }, "b" : [ 1 , 2 , 3 ]} ,
154
- [ 1 , 2 , 3 ] ,
168
+ # Since object will have arbitrary addresses, only need to ensure that
169
+ # the params string contains most of the string representation of the object.
170
+ expected_params_contains = [
171
+ "test_parameterize_case_complex_objects.A" ,
172
+ "test_parameterize_case_complex_objects.A" ,
173
+ "<function item_param at 0x" ,
174
+ '"a ": "<test_parameterize_case_complex_objects.A' ,
175
+ "<MagicMock id=" ,
176
+ "test_parameterize_case_complex_objects.A" ,
155
177
]
156
- assert len (spans ) == 9
157
- for i in range (len (spans ) - 1 ):
158
- extracted_params = json .loads (spans [i ].meta [test .PARAMETERS ])
159
- assert extracted_params == {"arguments" : {"item" : expected_params [i ]}, "metadata" : {}}
160
- assert "<function item_param at 0x" in json .loads (spans [8 ].meta [test .PARAMETERS ])["arguments" ]["item" ]
178
+ assert len (spans ) == 6
179
+ for i in range (len (expected_params_contains )):
180
+ assert expected_params_contains [i ] in spans [i ].meta [test .PARAMETERS ]
161
181
162
182
def test_skip (self ):
163
183
"""Test parametrize case."""
@@ -329,68 +349,3 @@ def test_service(ddspan):
329
349
file_name = os .path .basename (py_file .strpath )
330
350
rec = self .subprocess_run ("--ddtrace" , file_name )
331
351
assert 0 == rec .ret
332
-
333
-
334
- class A (object ):
335
- def __init__ (self , name , value ):
336
- self .name = name
337
- self .value = value
338
-
339
-
340
- simple_types = [st .none (), st .booleans (), st .text (), st .integers (), st .floats (allow_infinity = False , allow_nan = False )]
341
- complex_types = [st .functions (), st .dates (), st .decimals (), st .builds (A , name = st .text (), value = st .integers ())]
342
-
343
-
344
- @given (
345
- st .dictionaries (
346
- st .text (),
347
- st .one_of (
348
- st .lists (st .one_of (* simple_types )), st .dictionaries (st .text (), st .one_of (* simple_types )), * simple_types
349
- ),
350
- )
351
- )
352
- def test_custom_json_encoding_simple_types (obj ):
353
- """Ensures the _json.encode helper encodes simple objects."""
354
- encoded = _json_encode (obj )
355
- decoded = json .loads (encoded )
356
- assert obj == decoded
357
-
358
-
359
- @given (
360
- st .dictionaries (
361
- st .text (),
362
- st .one_of (
363
- st .lists (st .one_of (* complex_types )), st .dictionaries (st .text (), st .one_of (* complex_types )), * complex_types
364
- ),
365
- )
366
- )
367
- def test_custom_json_encoding_python_objects (obj ):
368
- """Ensures the _json_encode helper encodes complex objects into dicts of inner values or a string representation."""
369
- encoded = _json_encode (obj )
370
- obj = json .loads (
371
- json .dumps (obj , default = lambda x : getattr (x , "__dict__" , None ) if getattr (x , "__dict__" , None ) else repr (x ))
372
- )
373
- decoded = json .loads (encoded )
374
- assert obj == decoded
375
-
376
-
377
- def test_custom_json_encoding_side_effects ():
378
- """Ensures the _json_encode helper encodes objects with side effects (getattr, repr) without raising exceptions."""
379
- dict_side_effect = Exception ("side effect __dict__" )
380
- repr_side_effect = Exception ("side effect __repr__" )
381
-
382
- class B (object ):
383
- def __getattribute__ (self , item ):
384
- if item == "__dict__" :
385
- raise dict_side_effect
386
- raise AttributeError ()
387
-
388
- class C (object ):
389
- def __repr__ (self ):
390
- raise repr_side_effect
391
-
392
- obj = {"b" : B (), "c" : C ()}
393
- encoded = _json_encode (obj )
394
- decoded = json .loads (encoded )
395
- assert decoded ["b" ] == repr (dict_side_effect )
396
- assert decoded ["c" ] == repr (repr_side_effect )
0 commit comments