Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add filtering for flags and testsuites #834

Merged
merged 4 commits into from
Oct 4, 2024

Conversation

joseph-sentry
Copy link
Contributor

we want to be able to filter test results by a list of flags and by a
list of testsuite names so this adds that functionality.

this is done by adding testsuites and flags fields to the
TestResultsFilteringParameter GQL model

to filter by flags this uses the TestFlagBridge database model

@codecov-staging
Copy link

codecov-staging bot commented Oct 4, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

Copy link

codecov bot commented Oct 4, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 96.31%. Comparing base (16557ec) to head (38da329).
Report is 1 commits behind head on main.

✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #834   +/-   ##
=======================================
  Coverage   96.30%   96.31%           
=======================================
  Files         818      818           
  Lines       18960    18971   +11     
=======================================
+ Hits        18260    18271   +11     
  Misses        700      700           
Flag Coverage Δ
unit 92.63% <100.00%> (+<0.01%) ⬆️
unit-latest-uploader 92.63% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@codecov-qa
Copy link

codecov-qa bot commented Oct 4, 2024

❌ 6 Tests Failed:

Tests completed Failed Passed Skipped
2380 6 2374 6
View the top 3 failed tests by shortest run time
graphql_api.tests.test_test_result.TestResultTestCase test_fetch_test_result_name
Stack Traces | 0.323s run time
self = &lt;graphql_api.tests.test_test_result.TestResultTestCase testMethod=test_fetch_test_result_name&gt;

    def setUp(self):
        self.owner = OwnerFactory(username="randomOwner")
        self.repository = RepositoryFactory(
            author=self.owner,
        )
        self.test = TestFactory(
            name="Test\x1fName",
            repository=self.repository,
        )
    
        self.test_with_flag = TestFactory(
            name="Other Test",
            repository=self.repository,
        )
    
        flag = RepositoryFlagFactory(
            repository=self.repository, flag_name="test_flag_name"
        )
    
&gt;       _ = TestFlagBridgeFactory(repository=self.repository, flag=flag)

graphql_api/tests/test_test_result.py:39: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../local/lib/python3.12............/site-packages/factory/base.py:40: in __call__
    return cls.create(**kwargs)
.../local/lib/python3.12............/site-packages/factory/base.py:528: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
.../local/lib/python3.12....../site-packages/factory/django.py:117: in _generate
    return super()._generate(strategy, params)
.../local/lib/python3.12............/site-packages/factory/base.py:465: in _generate
    return step.build()
.../local/lib/python3.12.../site-packages/factory/builder.py:262: in build
    instance = self.factory_meta.instantiate(
.../local/lib/python3.12............/site-packages/factory/base.py:317: in instantiate
    return self.factory._create(model, *args, **kwargs)
.../local/lib/python3.12....../site-packages/factory/django.py:166: in _create
    return manager.create(*args, **kwargs)
.../local/lib/python3.12.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
.../local/lib/python3.12.../db/models/query.py:656: in create
    obj = self.model(**kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = &lt;TestFlagBridge: TestFlagBridge object (None)&gt;, args = ()
kwargs = {'repository': &lt;Repository: Repo&lt;Owner&lt;github/randomOwner&gt;/industry&gt;&gt;}
cls = &lt;class 'shared.django_apps.reports.models.TestFlagBridge'&gt;
opts = &lt;Options for TestFlagBridge&gt;, _setattr = &lt;built-in function setattr&gt;
_DEFERRED = &lt;Deferred field&gt;
fields_iter = &lt;tuple_iterator object at 0x7f248a609d50&gt;, val = None
field = &lt;django.db.models.fields.related.ForeignKey: test&gt;
is_related_object = True, rel_obj = &lt;Test: Test object (216)&gt;
property_names = frozenset({'pk'})

    def __init__(self, *args, **kwargs):
        # Alias some things as locals to avoid repeat global lookups
        cls = self.__class__
        opts = self._meta
        _setattr = setattr
        _DEFERRED = DEFERRED
        if opts.abstract:
            raise TypeError("Abstract models cannot be instantiated.")
    
        pre_init.send(sender=cls, args=args, kwargs=kwargs)
    
        # Set up the storage for instance state
        self._state = ModelState()
    
        # There is a rather weird disparity here; if kwargs, it's set, then args
        # overrides it. It should be one or the other; don't duplicate the work
        # The reason for the kwargs check is that standard iterator passes in by
        # args, and instantiation for iteration is 33% faster.
        if len(args) &gt; len(opts.concrete_fields):
            # Daft, but matches old exception sans the err msg.
            raise IndexError("Number of args exceeds number of fields")
    
        if not kwargs:
            fields_iter = iter(opts.concrete_fields)
            # The ordering of the zip calls matter - zip throws StopIteration
            # when an iter throws it. So if the first iter throws it, the second
            # is *not* consumed. We rely on this, so don't change the order
            # without changing the logic.
            for val, field in zip(args, fields_iter):
                if val is _DEFERRED:
                    continue
                _setattr(self, field.attname, val)
        else:
            # Slower, kwargs-ready version.
            fields_iter = iter(opts.fields)
            for val, field in zip(args, fields_iter):
                if val is _DEFERRED:
                    continue
                _setattr(self, field.attname, val)
                if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
                    raise TypeError(
                        f"{cls.__qualname__}() got both positional and "
                        f"keyword arguments for field '{field.name}'."
                    )
    
        # Now we're left with the unprocessed fields that *must* come from
        # keywords, or default.
    
        for field in fields_iter:
            is_related_object = False
            # Virtual field
            if field.attname not in kwargs and field.column is None:
                continue
            if kwargs:
                if isinstance(field.remote_field, ForeignObjectRel):
                    try:
                        # Assume object instance was passed in.
                        rel_obj = kwargs.pop(field.name)
                        is_related_object = True
                    except KeyError:
                        try:
                            # Object instance wasn't passed in -- must be an ID.
                            val = kwargs.pop(field.attname)
                        except KeyError:
                            val = field.get_default()
                else:
                    try:
                        val = kwargs.pop(field.attname)
                    except KeyError:
                        # This is done with an exception rather than the
                        # default argument on pop because we don't want
                        # get_default() to be evaluated, and then not used.
                        # Refs #12057.
                        val = field.get_default()
            else:
                val = field.get_default()
    
            if is_related_object:
                # If we are passed a related instance, set it using the
                # field.name instead of field.attname (e.g. "user" instead of
                # "user_id") so that the object gets properly cached (and type
                # checked) by the RelatedObjectDescriptor.
                if rel_obj is not _DEFERRED:
                    _setattr(self, field.name, rel_obj)
            else:
                if val is not _DEFERRED:
                    _setattr(self, field.attname, val)
    
        if kwargs:
            property_names = opts._property_names
            unexpected = ()
            for prop, value in kwargs.items():
                # Any remaining kwargs must correspond to properties or virtual
                # fields.
                if prop in property_names:
                    if value is not _DEFERRED:
                        _setattr(self, prop, value)
                else:
                    try:
                        opts.get_field(prop)
                    except FieldDoesNotExist:
                        unexpected += (prop,)
                    else:
                        if value is not _DEFERRED:
                            _setattr(self, prop, value)
            if unexpected:
                unexpected_names = ", ".join(repr(n) for n in unexpected)
&gt;               raise TypeError(
                    f"{cls.__name__}() got unexpected keyword arguments: "
                    f"{unexpected_names}"
                )
E               TypeError: TestFlagBridge() got unexpected keyword arguments: 'repository'

.../local/lib/python3.12.../db/models/base.py:567: TypeError
graphql_api.tests.test_test_result.TestResultTestCase test_fetch_test_result_updated_at
Stack Traces | 0.323s run time
self = &lt;graphql_api.tests.test_test_result.TestResultTestCase testMethod=test_fetch_test_result_updated_at&gt;

    def setUp(self):
        self.owner = OwnerFactory(username="randomOwner")
        self.repository = RepositoryFactory(
            author=self.owner,
        )
        self.test = TestFactory(
            name="Test\x1fName",
            repository=self.repository,
        )
    
        self.test_with_flag = TestFactory(
            name="Other Test",
            repository=self.repository,
        )
    
        flag = RepositoryFlagFactory(
            repository=self.repository, flag_name="test_flag_name"
        )
    
&gt;       _ = TestFlagBridgeFactory(repository=self.repository, flag=flag)

graphql_api/tests/test_test_result.py:39: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../local/lib/python3.12............/site-packages/factory/base.py:40: in __call__
    return cls.create(**kwargs)
.../local/lib/python3.12............/site-packages/factory/base.py:528: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
.../local/lib/python3.12....../site-packages/factory/django.py:117: in _generate
    return super()._generate(strategy, params)
.../local/lib/python3.12............/site-packages/factory/base.py:465: in _generate
    return step.build()
.../local/lib/python3.12.../site-packages/factory/builder.py:262: in build
    instance = self.factory_meta.instantiate(
.../local/lib/python3.12............/site-packages/factory/base.py:317: in instantiate
    return self.factory._create(model, *args, **kwargs)
.../local/lib/python3.12....../site-packages/factory/django.py:166: in _create
    return manager.create(*args, **kwargs)
.../local/lib/python3.12.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
.../local/lib/python3.12.../db/models/query.py:656: in create
    obj = self.model(**kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = &lt;TestFlagBridge: TestFlagBridge object (None)&gt;, args = ()
kwargs = {'repository': &lt;Repository: Repo&lt;Owner&lt;github/randomOwner&gt;/operation&gt;&gt;}
cls = &lt;class 'shared.django_apps.reports.models.TestFlagBridge'&gt;
opts = &lt;Options for TestFlagBridge&gt;, _setattr = &lt;built-in function setattr&gt;
_DEFERRED = &lt;Deferred field&gt;
fields_iter = &lt;tuple_iterator object at 0x7f248aa86e90&gt;, val = None
field = &lt;django.db.models.fields.related.ForeignKey: test&gt;
is_related_object = True, rel_obj = &lt;Test: Test object (219)&gt;
property_names = frozenset({'pk'})

    def __init__(self, *args, **kwargs):
        # Alias some things as locals to avoid repeat global lookups
        cls = self.__class__
        opts = self._meta
        _setattr = setattr
        _DEFERRED = DEFERRED
        if opts.abstract:
            raise TypeError("Abstract models cannot be instantiated.")
    
        pre_init.send(sender=cls, args=args, kwargs=kwargs)
    
        # Set up the storage for instance state
        self._state = ModelState()
    
        # There is a rather weird disparity here; if kwargs, it's set, then args
        # overrides it. It should be one or the other; don't duplicate the work
        # The reason for the kwargs check is that standard iterator passes in by
        # args, and instantiation for iteration is 33% faster.
        if len(args) &gt; len(opts.concrete_fields):
            # Daft, but matches old exception sans the err msg.
            raise IndexError("Number of args exceeds number of fields")
    
        if not kwargs:
            fields_iter = iter(opts.concrete_fields)
            # The ordering of the zip calls matter - zip throws StopIteration
            # when an iter throws it. So if the first iter throws it, the second
            # is *not* consumed. We rely on this, so don't change the order
            # without changing the logic.
            for val, field in zip(args, fields_iter):
                if val is _DEFERRED:
                    continue
                _setattr(self, field.attname, val)
        else:
            # Slower, kwargs-ready version.
            fields_iter = iter(opts.fields)
            for val, field in zip(args, fields_iter):
                if val is _DEFERRED:
                    continue
                _setattr(self, field.attname, val)
                if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
                    raise TypeError(
                        f"{cls.__qualname__}() got both positional and "
                        f"keyword arguments for field '{field.name}'."
                    )
    
        # Now we're left with the unprocessed fields that *must* come from
        # keywords, or default.
    
        for field in fields_iter:
            is_related_object = False
            # Virtual field
            if field.attname not in kwargs and field.column is None:
                continue
            if kwargs:
                if isinstance(field.remote_field, ForeignObjectRel):
                    try:
                        # Assume object instance was passed in.
                        rel_obj = kwargs.pop(field.name)
                        is_related_object = True
                    except KeyError:
                        try:
                            # Object instance wasn't passed in -- must be an ID.
                            val = kwargs.pop(field.attname)
                        except KeyError:
                            val = field.get_default()
                else:
                    try:
                        val = kwargs.pop(field.attname)
                    except KeyError:
                        # This is done with an exception rather than the
                        # default argument on pop because we don't want
                        # get_default() to be evaluated, and then not used.
                        # Refs #12057.
                        val = field.get_default()
            else:
                val = field.get_default()
    
            if is_related_object:
                # If we are passed a related instance, set it using the
                # field.name instead of field.attname (e.g. "user" instead of
                # "user_id") so that the object gets properly cached (and type
                # checked) by the RelatedObjectDescriptor.
                if rel_obj is not _DEFERRED:
                    _setattr(self, field.name, rel_obj)
            else:
                if val is not _DEFERRED:
                    _setattr(self, field.attname, val)
    
        if kwargs:
            property_names = opts._property_names
            unexpected = ()
            for prop, value in kwargs.items():
                # Any remaining kwargs must correspond to properties or virtual
                # fields.
                if prop in property_names:
                    if value is not _DEFERRED:
                        _setattr(self, prop, value)
                else:
                    try:
                        opts.get_field(prop)
                    except FieldDoesNotExist:
                        unexpected += (prop,)
                    else:
                        if value is not _DEFERRED:
                            _setattr(self, prop, value)
            if unexpected:
                unexpected_names = ", ".join(repr(n) for n in unexpected)
&gt;               raise TypeError(
                    f"{cls.__name__}() got unexpected keyword arguments: "
                    f"{unexpected_names}"
                )
E               TypeError: TestFlagBridge() got unexpected keyword arguments: 'repository'

.../local/lib/python3.12.../db/models/base.py:567: TypeError
graphql_api.tests.test_test_result.TestResultTestCase test_fetch_test_result_failure_rate
Stack Traces | 0.324s run time
self = &lt;graphql_api.tests.test_test_result.TestResultTestCase testMethod=test_fetch_test_result_failure_rate&gt;

    def setUp(self):
        self.owner = OwnerFactory(username="randomOwner")
        self.repository = RepositoryFactory(
            author=self.owner,
        )
        self.test = TestFactory(
            name="Test\x1fName",
            repository=self.repository,
        )
    
        self.test_with_flag = TestFactory(
            name="Other Test",
            repository=self.repository,
        )
    
        flag = RepositoryFlagFactory(
            repository=self.repository, flag_name="test_flag_name"
        )
    
&gt;       _ = TestFlagBridgeFactory(repository=self.repository, flag=flag)

graphql_api/tests/test_test_result.py:39: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
.../local/lib/python3.12............/site-packages/factory/base.py:40: in __call__
    return cls.create(**kwargs)
.../local/lib/python3.12............/site-packages/factory/base.py:528: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
.../local/lib/python3.12....../site-packages/factory/django.py:117: in _generate
    return super()._generate(strategy, params)
.../local/lib/python3.12............/site-packages/factory/base.py:465: in _generate
    return step.build()
.../local/lib/python3.12.../site-packages/factory/builder.py:262: in build
    instance = self.factory_meta.instantiate(
.../local/lib/python3.12............/site-packages/factory/base.py:317: in instantiate
    return self.factory._create(model, *args, **kwargs)
.../local/lib/python3.12....../site-packages/factory/django.py:166: in _create
    return manager.create(*args, **kwargs)
.../local/lib/python3.12.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
.../local/lib/python3.12.../db/models/query.py:656: in create
    obj = self.model(**kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = &lt;TestFlagBridge: TestFlagBridge object (None)&gt;, args = ()
kwargs = {'repository': &lt;Repository: Repo&lt;Owner&lt;github/randomOwner&gt;/move&gt;&gt;}
cls = &lt;class 'shared.django_apps.reports.models.TestFlagBridge'&gt;
opts = &lt;Options for TestFlagBridge&gt;, _setattr = &lt;built-in function setattr&gt;
_DEFERRED = &lt;Deferred field&gt;
fields_iter = &lt;tuple_iterator object at 0x7f248a60bfd0&gt;, val = None
field = &lt;django.db.models.fields.related.ForeignKey: test&gt;
is_related_object = True, rel_obj = &lt;Test: Test object (210)&gt;
property_names = frozenset({'pk'})

    def __init__(self, *args, **kwargs):
        # Alias some things as locals to avoid repeat global lookups
        cls = self.__class__
        opts = self._meta
        _setattr = setattr
        _DEFERRED = DEFERRED
        if opts.abstract:
            raise TypeError("Abstract models cannot be instantiated.")
    
        pre_init.send(sender=cls, args=args, kwargs=kwargs)
    
        # Set up the storage for instance state
        self._state = ModelState()
    
        # There is a rather weird disparity here; if kwargs, it's set, then args
        # overrides it. It should be one or the other; don't duplicate the work
        # The reason for the kwargs check is that standard iterator passes in by
        # args, and instantiation for iteration is 33% faster.
        if len(args) &gt; len(opts.concrete_fields):
            # Daft, but matches old exception sans the err msg.
            raise IndexError("Number of args exceeds number of fields")
    
        if not kwargs:
            fields_iter = iter(opts.concrete_fields)
            # The ordering of the zip calls matter - zip throws StopIteration
            # when an iter throws it. So if the first iter throws it, the second
            # is *not* consumed. We rely on this, so don't change the order
            # without changing the logic.
            for val, field in zip(args, fields_iter):
                if val is _DEFERRED:
                    continue
                _setattr(self, field.attname, val)
        else:
            # Slower, kwargs-ready version.
            fields_iter = iter(opts.fields)
            for val, field in zip(args, fields_iter):
                if val is _DEFERRED:
                    continue
                _setattr(self, field.attname, val)
                if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
                    raise TypeError(
                        f"{cls.__qualname__}() got both positional and "
                        f"keyword arguments for field '{field.name}'."
                    )
    
        # Now we're left with the unprocessed fields that *must* come from
        # keywords, or default.
    
        for field in fields_iter:
            is_related_object = False
            # Virtual field
            if field.attname not in kwargs and field.column is None:
                continue
            if kwargs:
                if isinstance(field.remote_field, ForeignObjectRel):
                    try:
                        # Assume object instance was passed in.
                        rel_obj = kwargs.pop(field.name)
                        is_related_object = True
                    except KeyError:
                        try:
                            # Object instance wasn't passed in -- must be an ID.
                            val = kwargs.pop(field.attname)
                        except KeyError:
                            val = field.get_default()
                else:
                    try:
                        val = kwargs.pop(field.attname)
                    except KeyError:
                        # This is done with an exception rather than the
                        # default argument on pop because we don't want
                        # get_default() to be evaluated, and then not used.
                        # Refs #12057.
                        val = field.get_default()
            else:
                val = field.get_default()
    
            if is_related_object:
                # If we are passed a related instance, set it using the
                # field.name instead of field.attname (e.g. "user" instead of
                # "user_id") so that the object gets properly cached (and type
                # checked) by the RelatedObjectDescriptor.
                if rel_obj is not _DEFERRED:
                    _setattr(self, field.name, rel_obj)
            else:
                if val is not _DEFERRED:
                    _setattr(self, field.attname, val)
    
        if kwargs:
            property_names = opts._property_names
            unexpected = ()
            for prop, value in kwargs.items():
                # Any remaining kwargs must correspond to properties or virtual
                # fields.
                if prop in property_names:
                    if value is not _DEFERRED:
                        _setattr(self, prop, value)
                else:
                    try:
                        opts.get_field(prop)
                    except FieldDoesNotExist:
                        unexpected += (prop,)
                    else:
                        if value is not _DEFERRED:
                            _setattr(self, prop, value)
            if unexpected:
                unexpected_names = ", ".join(repr(n) for n in unexpected)
&gt;               raise TypeError(
                    f"{cls.__name__}() got unexpected keyword arguments: "
                    f"{unexpected_names}"
                )
E               TypeError: TestFlagBridge() got unexpected keyword arguments: 'repository'

.../local/lib/python3.12.../db/models/base.py:567: TypeError

To view individual test run time comparison to the main branch, go to the Test Analytics Dashboard

Copy link

codecov-public-qa bot commented Oct 4, 2024

Test Failures Detected: Due to failing tests, we cannot provide coverage reports at this time.

❌ Failed Test Results:

Completed 2386 tests with 6 failed, 2374 passed and 6 skipped.

View the full list of failed tests

pytest

  • Class name: graphql_api.tests.test_test_result.TestResultTestCase
    Test name: test_fetch_test_result_avg_duration

    self = <graphql_api.tests.test_test_result.TestResultTestCase testMethod=test_fetch_test_result_avg_duration>

    def setUp(self):
    self.owner = OwnerFactory(username="randomOwner")
    self.repository = RepositoryFactory(
    author=self.owner,
    )
    self.test = TestFactory(
    name="Test\x1fName",
    repository=self.repository,
    )

    self.test_with_flag = TestFactory(
    name="Other Test",
    repository=self.repository,
    )

    flag = RepositoryFlagFactory(
    repository=self.repository, flag_name="test_flag_name"
    )

    > _ = TestFlagBridgeFactory(repository=self.repository, flag=flag)

    graphql_api/tests/test_test_result.py:39:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    .../local/lib/python3.12............/site-packages/factory/base.py:40: in __call__
    return cls.create(**kwargs)
    .../local/lib/python3.12............/site-packages/factory/base.py:528: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:117: in _generate
    return super()._generate(strategy, params)
    .../local/lib/python3.12............/site-packages/factory/base.py:465: in _generate
    return step.build()
    .../local/lib/python3.12.../site-packages/factory/builder.py:262: in build
    instance = self.factory_meta.instantiate(
    .../local/lib/python3.12............/site-packages/factory/base.py:317: in instantiate
    return self.factory._create(model, *args, **kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:166: in _create
    return manager.create(*args, **kwargs)
    .../local/lib/python3.12.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
    .../local/lib/python3.12.../db/models/query.py:656: in create
    obj = self.model(**kwargs)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <TestFlagBridge: TestFlagBridge object (None)>, args = ()
    kwargs = {'repository': <Repository: Repo<Owner<github/randomOwner>/surface>>}
    cls = <class 'shared.django_apps.reports.models.TestFlagBridge'>
    opts = <Options for TestFlagBridge>, _setattr = <built-in function setattr>
    _DEFERRED = <Deferred field>
    fields_iter = <tuple_iterator object at 0x7f248a50d300>, val = None
    field = <django.db.models.fields.related.ForeignKey: test>
    is_related_object = True, rel_obj = <Test: Test object (204)>
    property_names = frozenset({'pk'})

    def __init__(self, *args, **kwargs):
    # Alias some things as locals to avoid repeat global lookups
    cls = self.__class__
    opts = self._meta
    _setattr = setattr
    _DEFERRED = DEFERRED
    if opts.abstract:
    raise TypeError("Abstract models cannot be instantiated.")

    pre_init.send(sender=cls, args=args, kwargs=kwargs)

    # Set up the storage for instance state
    self._state = ModelState()

    # There is a rather weird disparity here; if kwargs, it's set, then args
    # overrides it. It should be one or the other; don't duplicate the work
    # The reason for the kwargs check is that standard iterator passes in by
    # args, and instantiation for iteration is 33% faster.
    if len(args) > len(opts.concrete_fields):
    # Daft, but matches old exception sans the err msg.
    raise IndexError("Number of args exceeds number of fields")

    if not kwargs:
    fields_iter = iter(opts.concrete_fields)
    # The ordering of the zip calls matter - zip throws StopIteration
    # when an iter throws it. So if the first iter throws it, the second
    # is *not* consumed. We rely on this, so don't change the order
    # without changing the logic.
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    else:
    # Slower, kwargs-ready version.
    fields_iter = iter(opts.fields)
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
    raise TypeError(
    f"{cls.__qualname__}() got both positional and "
    f"keyword arguments for field '{field.name}'."
    )

    # Now we're left with the unprocessed fields that *must* come from
    # keywords, or default.

    for field in fields_iter:
    is_related_object = False
    # Virtual field
    if field.attname not in kwargs and field.column is None:
    continue
    if kwargs:
    if isinstance(field.remote_field, ForeignObjectRel):
    try:
    # Assume object instance was passed in.
    rel_obj = kwargs.pop(field.name)
    is_related_object = True
    except KeyError:
    try:
    # Object instance wasn't passed in -- must be an ID.
    val = kwargs.pop(field.attname)
    except KeyError:
    val = field.get_default()
    else:
    try:
    val = kwargs.pop(field.attname)
    except KeyError:
    # This is done with an exception rather than the
    # default argument on pop because we don't want
    # get_default() to be evaluated, and then not used.
    # Refs #12057.
    val = field.get_default()
    else:
    val = field.get_default()

    if is_related_object:
    # If we are passed a related instance, set it using the
    # field.name instead of field.attname (e.g. "user" instead of
    # "user_id") so that the object gets properly cached (and type
    # checked) by the RelatedObjectDescriptor.
    if rel_obj is not _DEFERRED:
    _setattr(self, field.name, rel_obj)
    else:
    if val is not _DEFERRED:
    _setattr(self, field.attname, val)

    if kwargs:
    property_names = opts._property_names
    unexpected = ()
    for prop, value in kwargs.items():
    # Any remaining kwargs must correspond to properties or virtual
    # fields.
    if prop in property_names:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    else:
    try:
    opts.get_field(prop)
    except FieldDoesNotExist:
    unexpected += (prop,)
    else:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    if unexpected:
    unexpected_names = ", ".join(repr(n) for n in unexpected)
    > raise TypeError(
    f"{cls.__name__}() got unexpected keyword arguments: "
    f"{unexpected_names}"
    )
    E TypeError: TestFlagBridge() got unexpected keyword arguments: 'repository'

    .../local/lib/python3.12.../db/models/base.py:567: TypeError
  • Class name: graphql_api.tests.test_test_result.TestResultTestCase
    Test name: test_fetch_test_result_commits_failed

    self = <graphql_api.tests.test_test_result.TestResultTestCase testMethod=test_fetch_test_result_commits_failed>

    def setUp(self):
    self.owner = OwnerFactory(username="randomOwner")
    self.repository = RepositoryFactory(
    author=self.owner,
    )
    self.test = TestFactory(
    name="Test\x1fName",
    repository=self.repository,
    )

    self.test_with_flag = TestFactory(
    name="Other Test",
    repository=self.repository,
    )

    flag = RepositoryFlagFactory(
    repository=self.repository, flag_name="test_flag_name"
    )

    > _ = TestFlagBridgeFactory(repository=self.repository, flag=flag)

    graphql_api/tests/test_test_result.py:39:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    .../local/lib/python3.12............/site-packages/factory/base.py:40: in __call__
    return cls.create(**kwargs)
    .../local/lib/python3.12............/site-packages/factory/base.py:528: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:117: in _generate
    return super()._generate(strategy, params)
    .../local/lib/python3.12............/site-packages/factory/base.py:465: in _generate
    return step.build()
    .../local/lib/python3.12.../site-packages/factory/builder.py:262: in build
    instance = self.factory_meta.instantiate(
    .../local/lib/python3.12............/site-packages/factory/base.py:317: in instantiate
    return self.factory._create(model, *args, **kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:166: in _create
    return manager.create(*args, **kwargs)
    .../local/lib/python3.12.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
    .../local/lib/python3.12.../db/models/query.py:656: in create
    obj = self.model(**kwargs)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <TestFlagBridge: TestFlagBridge object (None)>, args = ()
    kwargs = {'repository': <Repository: Repo<Owner<github/randomOwner>/task>>}
    cls = <class 'shared.django_apps.reports.models.TestFlagBridge'>
    opts = <Options for TestFlagBridge>, _setattr = <built-in function setattr>
    _DEFERRED = <Deferred field>
    fields_iter = <tuple_iterator object at 0x7f248a685db0>, val = None
    field = <django.db.models.fields.related.ForeignKey: test>
    is_related_object = True, rel_obj = <Test: Test object (207)>
    property_names = frozenset({'pk'})

    def __init__(self, *args, **kwargs):
    # Alias some things as locals to avoid repeat global lookups
    cls = self.__class__
    opts = self._meta
    _setattr = setattr
    _DEFERRED = DEFERRED
    if opts.abstract:
    raise TypeError("Abstract models cannot be instantiated.")

    pre_init.send(sender=cls, args=args, kwargs=kwargs)

    # Set up the storage for instance state
    self._state = ModelState()

    # There is a rather weird disparity here; if kwargs, it's set, then args
    # overrides it. It should be one or the other; don't duplicate the work
    # The reason for the kwargs check is that standard iterator passes in by
    # args, and instantiation for iteration is 33% faster.
    if len(args) > len(opts.concrete_fields):
    # Daft, but matches old exception sans the err msg.
    raise IndexError("Number of args exceeds number of fields")

    if not kwargs:
    fields_iter = iter(opts.concrete_fields)
    # The ordering of the zip calls matter - zip throws StopIteration
    # when an iter throws it. So if the first iter throws it, the second
    # is *not* consumed. We rely on this, so don't change the order
    # without changing the logic.
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    else:
    # Slower, kwargs-ready version.
    fields_iter = iter(opts.fields)
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
    raise TypeError(
    f"{cls.__qualname__}() got both positional and "
    f"keyword arguments for field '{field.name}'."
    )

    # Now we're left with the unprocessed fields that *must* come from
    # keywords, or default.

    for field in fields_iter:
    is_related_object = False
    # Virtual field
    if field.attname not in kwargs and field.column is None:
    continue
    if kwargs:
    if isinstance(field.remote_field, ForeignObjectRel):
    try:
    # Assume object instance was passed in.
    rel_obj = kwargs.pop(field.name)
    is_related_object = True
    except KeyError:
    try:
    # Object instance wasn't passed in -- must be an ID.
    val = kwargs.pop(field.attname)
    except KeyError:
    val = field.get_default()
    else:
    try:
    val = kwargs.pop(field.attname)
    except KeyError:
    # This is done with an exception rather than the
    # default argument on pop because we don't want
    # get_default() to be evaluated, and then not used.
    # Refs #12057.
    val = field.get_default()
    else:
    val = field.get_default()

    if is_related_object:
    # If we are passed a related instance, set it using the
    # field.name instead of field.attname (e.g. "user" instead of
    # "user_id") so that the object gets properly cached (and type
    # checked) by the RelatedObjectDescriptor.
    if rel_obj is not _DEFERRED:
    _setattr(self, field.name, rel_obj)
    else:
    if val is not _DEFERRED:
    _setattr(self, field.attname, val)

    if kwargs:
    property_names = opts._property_names
    unexpected = ()
    for prop, value in kwargs.items():
    # Any remaining kwargs must correspond to properties or virtual
    # fields.
    if prop in property_names:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    else:
    try:
    opts.get_field(prop)
    except FieldDoesNotExist:
    unexpected += (prop,)
    else:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    if unexpected:
    unexpected_names = ", ".join(repr(n) for n in unexpected)
    > raise TypeError(
    f"{cls.__name__}() got unexpected keyword arguments: "
    f"{unexpected_names}"
    )
    E TypeError: TestFlagBridge() got unexpected keyword arguments: 'repository'

    .../local/lib/python3.12.../db/models/base.py:567: TypeError
  • Class name: graphql_api.tests.test_test_result.TestResultTestCase
    Test name: test_fetch_test_result_failure_rate

    self = <graphql_api.tests.test_test_result.TestResultTestCase testMethod=test_fetch_test_result_failure_rate>

    def setUp(self):
    self.owner = OwnerFactory(username="randomOwner")
    self.repository = RepositoryFactory(
    author=self.owner,
    )
    self.test = TestFactory(
    name="Test\x1fName",
    repository=self.repository,
    )

    self.test_with_flag = TestFactory(
    name="Other Test",
    repository=self.repository,
    )

    flag = RepositoryFlagFactory(
    repository=self.repository, flag_name="test_flag_name"
    )

    > _ = TestFlagBridgeFactory(repository=self.repository, flag=flag)

    graphql_api/tests/test_test_result.py:39:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    .../local/lib/python3.12............/site-packages/factory/base.py:40: in __call__
    return cls.create(**kwargs)
    .../local/lib/python3.12............/site-packages/factory/base.py:528: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:117: in _generate
    return super()._generate(strategy, params)
    .../local/lib/python3.12............/site-packages/factory/base.py:465: in _generate
    return step.build()
    .../local/lib/python3.12.../site-packages/factory/builder.py:262: in build
    instance = self.factory_meta.instantiate(
    .../local/lib/python3.12............/site-packages/factory/base.py:317: in instantiate
    return self.factory._create(model, *args, **kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:166: in _create
    return manager.create(*args, **kwargs)
    .../local/lib/python3.12.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
    .../local/lib/python3.12.../db/models/query.py:656: in create
    obj = self.model(**kwargs)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <TestFlagBridge: TestFlagBridge object (None)>, args = ()
    kwargs = {'repository': <Repository: Repo<Owner<github/randomOwner>/move>>}
    cls = <class 'shared.django_apps.reports.models.TestFlagBridge'>
    opts = <Options for TestFlagBridge>, _setattr = <built-in function setattr>
    _DEFERRED = <Deferred field>
    fields_iter = <tuple_iterator object at 0x7f248a60bfd0>, val = None
    field = <django.db.models.fields.related.ForeignKey: test>
    is_related_object = True, rel_obj = <Test: Test object (210)>
    property_names = frozenset({'pk'})

    def __init__(self, *args, **kwargs):
    # Alias some things as locals to avoid repeat global lookups
    cls = self.__class__
    opts = self._meta
    _setattr = setattr
    _DEFERRED = DEFERRED
    if opts.abstract:
    raise TypeError("Abstract models cannot be instantiated.")

    pre_init.send(sender=cls, args=args, kwargs=kwargs)

    # Set up the storage for instance state
    self._state = ModelState()

    # There is a rather weird disparity here; if kwargs, it's set, then args
    # overrides it. It should be one or the other; don't duplicate the work
    # The reason for the kwargs check is that standard iterator passes in by
    # args, and instantiation for iteration is 33% faster.
    if len(args) > len(opts.concrete_fields):
    # Daft, but matches old exception sans the err msg.
    raise IndexError("Number of args exceeds number of fields")

    if not kwargs:
    fields_iter = iter(opts.concrete_fields)
    # The ordering of the zip calls matter - zip throws StopIteration
    # when an iter throws it. So if the first iter throws it, the second
    # is *not* consumed. We rely on this, so don't change the order
    # without changing the logic.
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    else:
    # Slower, kwargs-ready version.
    fields_iter = iter(opts.fields)
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
    raise TypeError(
    f"{cls.__qualname__}() got both positional and "
    f"keyword arguments for field '{field.name}'."
    )

    # Now we're left with the unprocessed fields that *must* come from
    # keywords, or default.

    for field in fields_iter:
    is_related_object = False
    # Virtual field
    if field.attname not in kwargs and field.column is None:
    continue
    if kwargs:
    if isinstance(field.remote_field, ForeignObjectRel):
    try:
    # Assume object instance was passed in.
    rel_obj = kwargs.pop(field.name)
    is_related_object = True
    except KeyError:
    try:
    # Object instance wasn't passed in -- must be an ID.
    val = kwargs.pop(field.attname)
    except KeyError:
    val = field.get_default()
    else:
    try:
    val = kwargs.pop(field.attname)
    except KeyError:
    # This is done with an exception rather than the
    # default argument on pop because we don't want
    # get_default() to be evaluated, and then not used.
    # Refs #12057.
    val = field.get_default()
    else:
    val = field.get_default()

    if is_related_object:
    # If we are passed a related instance, set it using the
    # field.name instead of field.attname (e.g. "user" instead of
    # "user_id") so that the object gets properly cached (and type
    # checked) by the RelatedObjectDescriptor.
    if rel_obj is not _DEFERRED:
    _setattr(self, field.name, rel_obj)
    else:
    if val is not _DEFERRED:
    _setattr(self, field.attname, val)

    if kwargs:
    property_names = opts._property_names
    unexpected = ()
    for prop, value in kwargs.items():
    # Any remaining kwargs must correspond to properties or virtual
    # fields.
    if prop in property_names:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    else:
    try:
    opts.get_field(prop)
    except FieldDoesNotExist:
    unexpected += (prop,)
    else:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    if unexpected:
    unexpected_names = ", ".join(repr(n) for n in unexpected)
    > raise TypeError(
    f"{cls.__name__}() got unexpected keyword arguments: "
    f"{unexpected_names}"
    )
    E TypeError: TestFlagBridge() got unexpected keyword arguments: 'repository'

    .../local/lib/python3.12.../db/models/base.py:567: TypeError
  • Class name: graphql_api.tests.test_test_result.TestResultTestCase
    Test name: test_fetch_test_result_last_duration

    self = <graphql_api.tests.test_test_result.TestResultTestCase testMethod=test_fetch_test_result_last_duration>

    def setUp(self):
    self.owner = OwnerFactory(username="randomOwner")
    self.repository = RepositoryFactory(
    author=self.owner,
    )
    self.test = TestFactory(
    name="Test\x1fName",
    repository=self.repository,
    )

    self.test_with_flag = TestFactory(
    name="Other Test",
    repository=self.repository,
    )

    flag = RepositoryFlagFactory(
    repository=self.repository, flag_name="test_flag_name"
    )

    > _ = TestFlagBridgeFactory(repository=self.repository, flag=flag)

    graphql_api/tests/test_test_result.py:39:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    .../local/lib/python3.12............/site-packages/factory/base.py:40: in __call__
    return cls.create(**kwargs)
    .../local/lib/python3.12............/site-packages/factory/base.py:528: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:117: in _generate
    return super()._generate(strategy, params)
    .../local/lib/python3.12............/site-packages/factory/base.py:465: in _generate
    return step.build()
    .../local/lib/python3.12.../site-packages/factory/builder.py:262: in build
    instance = self.factory_meta.instantiate(
    .../local/lib/python3.12............/site-packages/factory/base.py:317: in instantiate
    return self.factory._create(model, *args, **kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:166: in _create
    return manager.create(*args, **kwargs)
    .../local/lib/python3.12.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
    .../local/lib/python3.12.../db/models/query.py:656: in create
    obj = self.model(**kwargs)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <TestFlagBridge: TestFlagBridge object (None)>, args = ()
    kwargs = {'repository': <Repository: Repo<Owner<github/randomOwner>/treatment>>}
    cls = <class 'shared.django_apps.reports.models.TestFlagBridge'>
    opts = <Options for TestFlagBridge>, _setattr = <built-in function setattr>
    _DEFERRED = <Deferred field>
    fields_iter = <tuple_iterator object at 0x7f248abe8070>, val = None
    field = <django.db.models.fields.related.ForeignKey: test>
    is_related_object = True, rel_obj = <Test: Test object (213)>
    property_names = frozenset({'pk'})

    def __init__(self, *args, **kwargs):
    # Alias some things as locals to avoid repeat global lookups
    cls = self.__class__
    opts = self._meta
    _setattr = setattr
    _DEFERRED = DEFERRED
    if opts.abstract:
    raise TypeError("Abstract models cannot be instantiated.")

    pre_init.send(sender=cls, args=args, kwargs=kwargs)

    # Set up the storage for instance state
    self._state = ModelState()

    # There is a rather weird disparity here; if kwargs, it's set, then args
    # overrides it. It should be one or the other; don't duplicate the work
    # The reason for the kwargs check is that standard iterator passes in by
    # args, and instantiation for iteration is 33% faster.
    if len(args) > len(opts.concrete_fields):
    # Daft, but matches old exception sans the err msg.
    raise IndexError("Number of args exceeds number of fields")

    if not kwargs:
    fields_iter = iter(opts.concrete_fields)
    # The ordering of the zip calls matter - zip throws StopIteration
    # when an iter throws it. So if the first iter throws it, the second
    # is *not* consumed. We rely on this, so don't change the order
    # without changing the logic.
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    else:
    # Slower, kwargs-ready version.
    fields_iter = iter(opts.fields)
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
    raise TypeError(
    f"{cls.__qualname__}() got both positional and "
    f"keyword arguments for field '{field.name}'."
    )

    # Now we're left with the unprocessed fields that *must* come from
    # keywords, or default.

    for field in fields_iter:
    is_related_object = False
    # Virtual field
    if field.attname not in kwargs and field.column is None:
    continue
    if kwargs:
    if isinstance(field.remote_field, ForeignObjectRel):
    try:
    # Assume object instance was passed in.
    rel_obj = kwargs.pop(field.name)
    is_related_object = True
    except KeyError:
    try:
    # Object instance wasn't passed in -- must be an ID.
    val = kwargs.pop(field.attname)
    except KeyError:
    val = field.get_default()
    else:
    try:
    val = kwargs.pop(field.attname)
    except KeyError:
    # This is done with an exception rather than the
    # default argument on pop because we don't want
    # get_default() to be evaluated, and then not used.
    # Refs #12057.
    val = field.get_default()
    else:
    val = field.get_default()

    if is_related_object:
    # If we are passed a related instance, set it using the
    # field.name instead of field.attname (e.g. "user" instead of
    # "user_id") so that the object gets properly cached (and type
    # checked) by the RelatedObjectDescriptor.
    if rel_obj is not _DEFERRED:
    _setattr(self, field.name, rel_obj)
    else:
    if val is not _DEFERRED:
    _setattr(self, field.attname, val)

    if kwargs:
    property_names = opts._property_names
    unexpected = ()
    for prop, value in kwargs.items():
    # Any remaining kwargs must correspond to properties or virtual
    # fields.
    if prop in property_names:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    else:
    try:
    opts.get_field(prop)
    except FieldDoesNotExist:
    unexpected += (prop,)
    else:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    if unexpected:
    unexpected_names = ", ".join(repr(n) for n in unexpected)
    > raise TypeError(
    f"{cls.__name__}() got unexpected keyword arguments: "
    f"{unexpected_names}"
    )
    E TypeError: TestFlagBridge() got unexpected keyword arguments: 'repository'

    .../local/lib/python3.12.../db/models/base.py:567: TypeError
  • Class name: graphql_api.tests.test_test_result.TestResultTestCase
    Test name: test_fetch_test_result_name

    self = <graphql_api.tests.test_test_result.TestResultTestCase testMethod=test_fetch_test_result_name>

    def setUp(self):
    self.owner = OwnerFactory(username="randomOwner")
    self.repository = RepositoryFactory(
    author=self.owner,
    )
    self.test = TestFactory(
    name="Test\x1fName",
    repository=self.repository,
    )

    self.test_with_flag = TestFactory(
    name="Other Test",
    repository=self.repository,
    )

    flag = RepositoryFlagFactory(
    repository=self.repository, flag_name="test_flag_name"
    )

    > _ = TestFlagBridgeFactory(repository=self.repository, flag=flag)

    graphql_api/tests/test_test_result.py:39:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    .../local/lib/python3.12............/site-packages/factory/base.py:40: in __call__
    return cls.create(**kwargs)
    .../local/lib/python3.12............/site-packages/factory/base.py:528: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:117: in _generate
    return super()._generate(strategy, params)
    .../local/lib/python3.12............/site-packages/factory/base.py:465: in _generate
    return step.build()
    .../local/lib/python3.12.../site-packages/factory/builder.py:262: in build
    instance = self.factory_meta.instantiate(
    .../local/lib/python3.12............/site-packages/factory/base.py:317: in instantiate
    return self.factory._create(model, *args, **kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:166: in _create
    return manager.create(*args, **kwargs)
    .../local/lib/python3.12.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
    .../local/lib/python3.12.../db/models/query.py:656: in create
    obj = self.model(**kwargs)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <TestFlagBridge: TestFlagBridge object (None)>, args = ()
    kwargs = {'repository': <Repository: Repo<Owner<github/randomOwner>/industry>>}
    cls = <class 'shared.django_apps.reports.models.TestFlagBridge'>
    opts = <Options for TestFlagBridge>, _setattr = <built-in function setattr>
    _DEFERRED = <Deferred field>
    fields_iter = <tuple_iterator object at 0x7f248a609d50>, val = None
    field = <django.db.models.fields.related.ForeignKey: test>
    is_related_object = True, rel_obj = <Test: Test object (216)>
    property_names = frozenset({'pk'})

    def __init__(self, *args, **kwargs):
    # Alias some things as locals to avoid repeat global lookups
    cls = self.__class__
    opts = self._meta
    _setattr = setattr
    _DEFERRED = DEFERRED
    if opts.abstract:
    raise TypeError("Abstract models cannot be instantiated.")

    pre_init.send(sender=cls, args=args, kwargs=kwargs)

    # Set up the storage for instance state
    self._state = ModelState()

    # There is a rather weird disparity here; if kwargs, it's set, then args
    # overrides it. It should be one or the other; don't duplicate the work
    # The reason for the kwargs check is that standard iterator passes in by
    # args, and instantiation for iteration is 33% faster.
    if len(args) > len(opts.concrete_fields):
    # Daft, but matches old exception sans the err msg.
    raise IndexError("Number of args exceeds number of fields")

    if not kwargs:
    fields_iter = iter(opts.concrete_fields)
    # The ordering of the zip calls matter - zip throws StopIteration
    # when an iter throws it. So if the first iter throws it, the second
    # is *not* consumed. We rely on this, so don't change the order
    # without changing the logic.
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    else:
    # Slower, kwargs-ready version.
    fields_iter = iter(opts.fields)
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
    raise TypeError(
    f"{cls.__qualname__}() got both positional and "
    f"keyword arguments for field '{field.name}'."
    )

    # Now we're left with the unprocessed fields that *must* come from
    # keywords, or default.

    for field in fields_iter:
    is_related_object = False
    # Virtual field
    if field.attname not in kwargs and field.column is None:
    continue
    if kwargs:
    if isinstance(field.remote_field, ForeignObjectRel):
    try:
    # Assume object instance was passed in.
    rel_obj = kwargs.pop(field.name)
    is_related_object = True
    except KeyError:
    try:
    # Object instance wasn't passed in -- must be an ID.
    val = kwargs.pop(field.attname)
    except KeyError:
    val = field.get_default()
    else:
    try:
    val = kwargs.pop(field.attname)
    except KeyError:
    # This is done with an exception rather than the
    # default argument on pop because we don't want
    # get_default() to be evaluated, and then not used.
    # Refs #12057.
    val = field.get_default()
    else:
    val = field.get_default()

    if is_related_object:
    # If we are passed a related instance, set it using the
    # field.name instead of field.attname (e.g. "user" instead of
    # "user_id") so that the object gets properly cached (and type
    # checked) by the RelatedObjectDescriptor.
    if rel_obj is not _DEFERRED:
    _setattr(self, field.name, rel_obj)
    else:
    if val is not _DEFERRED:
    _setattr(self, field.attname, val)

    if kwargs:
    property_names = opts._property_names
    unexpected = ()
    for prop, value in kwargs.items():
    # Any remaining kwargs must correspond to properties or virtual
    # fields.
    if prop in property_names:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    else:
    try:
    opts.get_field(prop)
    except FieldDoesNotExist:
    unexpected += (prop,)
    else:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    if unexpected:
    unexpected_names = ", ".join(repr(n) for n in unexpected)
    > raise TypeError(
    f"{cls.__name__}() got unexpected keyword arguments: "
    f"{unexpected_names}"
    )
    E TypeError: TestFlagBridge() got unexpected keyword arguments: 'repository'

    .../local/lib/python3.12.../db/models/base.py:567: TypeError
  • Class name: graphql_api.tests.test_test_result.TestResultTestCase
    Test name: test_fetch_test_result_updated_at

    self = <graphql_api.tests.test_test_result.TestResultTestCase testMethod=test_fetch_test_result_updated_at>

    def setUp(self):
    self.owner = OwnerFactory(username="randomOwner")
    self.repository = RepositoryFactory(
    author=self.owner,
    )
    self.test = TestFactory(
    name="Test\x1fName",
    repository=self.repository,
    )

    self.test_with_flag = TestFactory(
    name="Other Test",
    repository=self.repository,
    )

    flag = RepositoryFlagFactory(
    repository=self.repository, flag_name="test_flag_name"
    )

    > _ = TestFlagBridgeFactory(repository=self.repository, flag=flag)

    graphql_api/tests/test_test_result.py:39:
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    .../local/lib/python3.12............/site-packages/factory/base.py:40: in __call__
    return cls.create(**kwargs)
    .../local/lib/python3.12............/site-packages/factory/base.py:528: in create
    return cls._generate(enums.CREATE_STRATEGY, kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:117: in _generate
    return super()._generate(strategy, params)
    .../local/lib/python3.12............/site-packages/factory/base.py:465: in _generate
    return step.build()
    .../local/lib/python3.12.../site-packages/factory/builder.py:262: in build
    instance = self.factory_meta.instantiate(
    .../local/lib/python3.12............/site-packages/factory/base.py:317: in instantiate
    return self.factory._create(model, *args, **kwargs)
    .../local/lib/python3.12....../site-packages/factory/django.py:166: in _create
    return manager.create(*args, **kwargs)
    .../local/lib/python3.12.../db/models/manager.py:87: in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
    .../local/lib/python3.12.../db/models/query.py:656: in create
    obj = self.model(**kwargs)
    _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

    self = <TestFlagBridge: TestFlagBridge object (None)>, args = ()
    kwargs = {'repository': <Repository: Repo<Owner<github/randomOwner>/operation>>}
    cls = <class 'shared.django_apps.reports.models.TestFlagBridge'>
    opts = <Options for TestFlagBridge>, _setattr = <built-in function setattr>
    _DEFERRED = <Deferred field>
    fields_iter = <tuple_iterator object at 0x7f248aa86e90>, val = None
    field = <django.db.models.fields.related.ForeignKey: test>
    is_related_object = True, rel_obj = <Test: Test object (219)>
    property_names = frozenset({'pk'})

    def __init__(self, *args, **kwargs):
    # Alias some things as locals to avoid repeat global lookups
    cls = self.__class__
    opts = self._meta
    _setattr = setattr
    _DEFERRED = DEFERRED
    if opts.abstract:
    raise TypeError("Abstract models cannot be instantiated.")

    pre_init.send(sender=cls, args=args, kwargs=kwargs)

    # Set up the storage for instance state
    self._state = ModelState()

    # There is a rather weird disparity here; if kwargs, it's set, then args
    # overrides it. It should be one or the other; don't duplicate the work
    # The reason for the kwargs check is that standard iterator passes in by
    # args, and instantiation for iteration is 33% faster.
    if len(args) > len(opts.concrete_fields):
    # Daft, but matches old exception sans the err msg.
    raise IndexError("Number of args exceeds number of fields")

    if not kwargs:
    fields_iter = iter(opts.concrete_fields)
    # The ordering of the zip calls matter - zip throws StopIteration
    # when an iter throws it. So if the first iter throws it, the second
    # is *not* consumed. We rely on this, so don't change the order
    # without changing the logic.
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    else:
    # Slower, kwargs-ready version.
    fields_iter = iter(opts.fields)
    for val, field in zip(args, fields_iter):
    if val is _DEFERRED:
    continue
    _setattr(self, field.attname, val)
    if kwargs.pop(field.name, NOT_PROVIDED) is not NOT_PROVIDED:
    raise TypeError(
    f"{cls.__qualname__}() got both positional and "
    f"keyword arguments for field '{field.name}'."
    )

    # Now we're left with the unprocessed fields that *must* come from
    # keywords, or default.

    for field in fields_iter:
    is_related_object = False
    # Virtual field
    if field.attname not in kwargs and field.column is None:
    continue
    if kwargs:
    if isinstance(field.remote_field, ForeignObjectRel):
    try:
    # Assume object instance was passed in.
    rel_obj = kwargs.pop(field.name)
    is_related_object = True
    except KeyError:
    try:
    # Object instance wasn't passed in -- must be an ID.
    val = kwargs.pop(field.attname)
    except KeyError:
    val = field.get_default()
    else:
    try:
    val = kwargs.pop(field.attname)
    except KeyError:
    # This is done with an exception rather than the
    # default argument on pop because we don't want
    # get_default() to be evaluated, and then not used.
    # Refs #12057.
    val = field.get_default()
    else:
    val = field.get_default()

    if is_related_object:
    # If we are passed a related instance, set it using the
    # field.name instead of field.attname (e.g. "user" instead of
    # "user_id") so that the object gets properly cached (and type
    # checked) by the RelatedObjectDescriptor.
    if rel_obj is not _DEFERRED:
    _setattr(self, field.name, rel_obj)
    else:
    if val is not _DEFERRED:
    _setattr(self, field.attname, val)

    if kwargs:
    property_names = opts._property_names
    unexpected = ()
    for prop, value in kwargs.items():
    # Any remaining kwargs must correspond to properties or virtual
    # fields.
    if prop in property_names:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    else:
    try:
    opts.get_field(prop)
    except FieldDoesNotExist:
    unexpected += (prop,)
    else:
    if value is not _DEFERRED:
    _setattr(self, prop, value)
    if unexpected:
    unexpected_names = ", ".join(repr(n) for n in unexpected)
    > raise TypeError(
    f"{cls.__name__}() got unexpected keyword arguments: "
    f"{unexpected_names}"
    )
    E TypeError: TestFlagBridge() got unexpected keyword arguments: 'repository'

    .../local/lib/python3.12.../db/models/base.py:567: TypeError

@joseph-sentry joseph-sentry force-pushed the joseph/filter-testsuite-and-flag branch from 9082c8f to 4d9ff63 Compare October 4, 2024 16:23
we want to be able to filter test results by a list of flags and by a
list of testsuite names so this adds that functionality.

this is done by adding testsuites and flags fields to the
TestResultsFilteringParameter GQL model

to filter by flags this uses the TestFlagBridge database model
@joseph-sentry joseph-sentry force-pushed the joseph/filter-testsuite-and-flag branch from 4d9ff63 to c925351 Compare October 4, 2024 17:00
@@ -1,6 +1,8 @@
input TestResultsFilters {
branch: String
parameter: TestResultsFilterParameter
testsuites: [String!]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: test_suites?

@@ -554,6 +554,8 @@ async def resolve_test_results(
repoid=repository.repoid,
branch=filters.get("branch") if filters else None,
parameter=generate_test_results_param,
testsuites=filters.get("testsuites") if filters else None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_suites

Frontend will likely name the variable testSuites which will get converted to test_suites due to

schema = make_executable_schema(types, *bindables, convert_names_case=True)

@@ -63,6 +64,8 @@ def generate_test_results(
branch: str | None = None,
history: dt.timedelta = dt.timedelta(days=30),
parameter: GENERATE_TEST_RESULT_PARAM | None = None,
testsuites: list[str] | None = None,
flags: list[str] | None = None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remember to update the function description

Copy link
Contributor

@ajay-sentry ajay-sentry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solid

@joseph-sentry joseph-sentry marked this pull request as ready for review October 4, 2024 17:47
@joseph-sentry joseph-sentry requested a review from a team as a code owner October 4, 2024 17:47
@joseph-sentry joseph-sentry added this pull request to the merge queue Oct 4, 2024
Merged via the queue into main with commit 6a28fb7 Oct 4, 2024
18 of 19 checks passed
@joseph-sentry joseph-sentry deleted the joseph/filter-testsuite-and-flag branch October 4, 2024 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants