How to use apply_presentation method in autotest

Best Python code snippet using autotest_python

models.py

Source:models.py Github

copy

Full Screen

1from django.db import models as dbmodels, connection2from autotest_lib.frontend.afe import model_logic, readonly_connection3_quote_name = connection.ops.quote_name4class TempManager(model_logic.ExtendedManager):5 """A Temp Manager."""6 _GROUP_COUNT_NAME = 'group_count'7 def _get_key_unless_is_function(self, field):8 if '(' in field:9 return field10 return self.get_key_on_this_table(field)11 def _get_field_names(self, fields, extra_select_fields={}):12 field_names = []13 for field in fields:14 if field in extra_select_fields:15 field_names.append(extra_select_fields[field][0])16 else:17 field_names.append(self._get_key_unless_is_function(field))18 return field_names19 def _get_group_query_sql(self, query, group_by):20 compiler = query.query.get_compiler(using=query.db)21 sql, params = compiler.as_sql()22 # insert GROUP BY clause into query23 group_fields = self._get_field_names(group_by, query.query.extra_select)24 group_by_clause = ' GROUP BY ' + ', '.join(group_fields)25 group_by_position = sql.rfind('ORDER BY')26 if group_by_position == -1:27 group_by_position = len(sql)28 sql = (sql[:group_by_position] +29 group_by_clause + ' ' +30 sql[group_by_position:])31 return sql, params32 def _get_column_names(self, cursor):33 """Gets the column names from the cursor description.34 This method exists so that it can be mocked in the unit test for35 sqlite3 compatibility.36 """37 return [column_info[0] for column_info in cursor.description]38 def execute_group_query(self, query, group_by):39 """Performs the given query grouped by the specified fields.40 The given query's extra select fields are added.41 @param query: The query to perform.42 @param group_by: The fields by which to group.43 @return A list of dicts, where each dict corresponds to single row and44 contains a key for each grouped field as well as all of the extra45 select fields.46 """47 sql, params = self._get_group_query_sql(query, group_by)48 cursor = readonly_connection.cursor()49 cursor.execute(sql, params)50 field_names = self._get_column_names(cursor)51 row_dicts = [dict(zip(field_names, row)) for row in cursor.fetchall()]52 return row_dicts53 def get_count_sql(self, query):54 """Get SQL to select a per-group count of unique matches for a query.55 @param query: The query to use.56 @return A tuple (field alias, field SQL).57 """58 if query.query.distinct:59 pk_field = self.get_key_on_this_table()60 count_sql = 'COUNT(DISTINCT %s)' % pk_field61 else:62 count_sql = 'COUNT(1)'63 return self._GROUP_COUNT_NAME, count_sql64 def _get_num_groups_sql(self, query, group_by):65 group_fields = self._get_field_names(group_by, query.query.extra_select)66 query = query.order_by() # this can mess up the query and isn't needed67 compiler = query.query.get_compiler(using=query.db)68 sql, params = compiler.as_sql()69 from_ = sql[sql.find(' FROM'):]70 return ('SELECT DISTINCT %s %s' % (','.join(group_fields),71 from_),72 params)73 def _cursor_rowcount(self, cursor):74 """To be stubbed by tests"""75 return cursor.rowcount76 def get_num_groups(self, query, group_by):77 """Gets the number of distinct groups for a query.78 @param query: The query to use.79 @param group_by: The fields by which to group.80 @return The number of distinct groups for the given query grouped by81 the fields in group_by.82 """83 sql, params = self._get_num_groups_sql(query, group_by)84 cursor = readonly_connection.cursor()85 cursor.execute(sql, params)86 return self._cursor_rowcount(cursor)87class Machine(dbmodels.Model):88 """Models a machine."""89 machine_idx = dbmodels.AutoField(primary_key=True)90 hostname = dbmodels.CharField(unique=True, max_length=255)91 machine_group = dbmodels.CharField(blank=True, max_length=240)92 owner = dbmodels.CharField(blank=True, max_length=240)93 class Meta:94 """Metadata for class Machine."""95 db_table = 'tko_machines'96class Kernel(dbmodels.Model):97 """Models a kernel."""98 kernel_idx = dbmodels.AutoField(primary_key=True)99 kernel_hash = dbmodels.CharField(max_length=105, editable=False)100 base = dbmodels.CharField(max_length=90)101 printable = dbmodels.CharField(max_length=300)102 class Meta:103 """Metadata for class Kernel."""104 db_table = 'tko_kernels'105class Patch(dbmodels.Model):106 """Models a patch."""107 kernel = dbmodels.ForeignKey(Kernel, db_column='kernel_idx')108 name = dbmodels.CharField(blank=True, max_length=240)109 url = dbmodels.CharField(blank=True, max_length=900)110 the_hash = dbmodels.CharField(blank=True, max_length=105, db_column='hash')111 class Meta:112 """Metadata for class Patch."""113 db_table = 'tko_patches'114class Status(dbmodels.Model):115 """Models a status."""116 status_idx = dbmodels.AutoField(primary_key=True)117 word = dbmodels.CharField(max_length=30)118 class Meta:119 """Metadata for class Status."""120 db_table = 'tko_status'121class Job(dbmodels.Model, model_logic.ModelExtensions):122 """Models a job."""123 job_idx = dbmodels.AutoField(primary_key=True)124 tag = dbmodels.CharField(unique=True, max_length=100)125 label = dbmodels.CharField(max_length=300)126 username = dbmodels.CharField(max_length=240)127 machine = dbmodels.ForeignKey(Machine, db_column='machine_idx')128 queued_time = dbmodels.DateTimeField(null=True, blank=True)129 started_time = dbmodels.DateTimeField(null=True, blank=True)130 finished_time = dbmodels.DateTimeField(null=True, blank=True)131 afe_job_id = dbmodels.IntegerField(null=True, default=None)132 objects = model_logic.ExtendedManager()133 class Meta:134 """Metadata for class Job."""135 db_table = 'tko_jobs'136class JobKeyval(dbmodels.Model):137 """Models a job keyval."""138 job = dbmodels.ForeignKey(Job)139 key = dbmodels.CharField(max_length=90)140 value = dbmodels.CharField(blank=True, max_length=300)141 class Meta:142 """Metadata for class JobKeyval."""143 db_table = 'tko_job_keyvals'144class Test(dbmodels.Model, model_logic.ModelExtensions,145 model_logic.ModelWithAttributes):146 """Models a test."""147 test_idx = dbmodels.AutoField(primary_key=True)148 job = dbmodels.ForeignKey(Job, db_column='job_idx')149 test = dbmodels.CharField(max_length=300)150 subdir = dbmodels.CharField(blank=True, max_length=300)151 kernel = dbmodels.ForeignKey(Kernel, db_column='kernel_idx')152 status = dbmodels.ForeignKey(Status, db_column='status')153 reason = dbmodels.CharField(blank=True, max_length=3072)154 machine = dbmodels.ForeignKey(Machine, db_column='machine_idx')155 finished_time = dbmodels.DateTimeField(null=True, blank=True)156 started_time = dbmodels.DateTimeField(null=True, blank=True)157 invalid = dbmodels.BooleanField(default=False)158 invalidates_test = dbmodels.ForeignKey(159 'self', null=True, db_column='invalidates_test_idx',160 related_name='invalidates_test_set')161 objects = model_logic.ExtendedManager()162 def _get_attribute_model_and_args(self, attribute):163 return TestAttribute, dict(test=self, attribute=attribute,164 user_created=True)165 def set_attribute(self, attribute, value):166 # ensure non-user-created attributes remain immutable167 try:168 TestAttribute.objects.get(test=self, attribute=attribute,169 user_created=False)170 raise ValueError('Attribute %s already exists for test %s and is '171 'immutable' % (attribute, self.test_idx))172 except TestAttribute.DoesNotExist:173 super(Test, self).set_attribute(attribute, value)174 class Meta:175 """Metadata for class Test."""176 db_table = 'tko_tests'177class TestAttribute(dbmodels.Model, model_logic.ModelExtensions):178 """Models a test attribute."""179 test = dbmodels.ForeignKey(Test, db_column='test_idx')180 attribute = dbmodels.CharField(max_length=90)181 value = dbmodels.CharField(blank=True, max_length=300)182 user_created = dbmodels.BooleanField(default=False)183 objects = model_logic.ExtendedManager()184 class Meta:185 """Metadata for class TestAttribute."""186 db_table = 'tko_test_attributes'187class IterationAttribute(dbmodels.Model, model_logic.ModelExtensions):188 """Models an iteration attribute."""189 # This isn't really a primary key, but it's necessary to appease Django190 # and is harmless as long as we're careful.191 test = dbmodels.ForeignKey(Test, db_column='test_idx', primary_key=True)192 iteration = dbmodels.IntegerField()193 attribute = dbmodels.CharField(max_length=90)194 value = dbmodels.CharField(blank=True, max_length=300)195 objects = model_logic.ExtendedManager()196 class Meta:197 """Metadata for class IterationAttribute."""198 db_table = 'tko_iteration_attributes'199class IterationResult(dbmodels.Model, model_logic.ModelExtensions):200 """Models an iteration result."""201 # See comment on IterationAttribute regarding primary_key=True.202 test = dbmodels.ForeignKey(Test, db_column='test_idx', primary_key=True)203 iteration = dbmodels.IntegerField()204 attribute = dbmodels.CharField(max_length=256)205 value = dbmodels.FloatField(null=True, blank=True)206 objects = model_logic.ExtendedManager()207 class Meta:208 """Metadata for class IterationResult."""209 db_table = 'tko_iteration_result'210class TestLabel(dbmodels.Model, model_logic.ModelExtensions):211 """Models a test label."""212 name = dbmodels.CharField(max_length=80, unique=True)213 description = dbmodels.TextField(blank=True)214 tests = dbmodels.ManyToManyField(Test, blank=True,215 db_table='tko_test_labels_tests')216 name_field = 'name'217 objects = model_logic.ExtendedManager()218 class Meta:219 """Metadata for class TestLabel."""220 db_table = 'tko_test_labels'221class SavedQuery(dbmodels.Model, model_logic.ModelExtensions):222 """Models a saved query."""223 # TODO: change this to foreign key once DBs are merged.224 owner = dbmodels.CharField(max_length=80)225 name = dbmodels.CharField(max_length=100)226 url_token = dbmodels.TextField()227 class Meta:228 """Metadata for class SavedQuery."""229 db_table = 'tko_saved_queries'230# Views.231class TestViewManager(TempManager):232 """A Test View Manager."""233 def get_query_set(self):234 query = super(TestViewManager, self).get_query_set()235 # add extra fields to selects, using the SQL itself as the "alias"236 extra_select = dict((sql, sql)237 for sql in self.model.extra_fields.iterkeys())238 return query.extra(select=extra_select)239 def _get_include_exclude_suffix(self, exclude):240 if exclude:241 return '_exclude'242 return '_include'243 def _add_attribute_join(self, query_set, join_condition,244 suffix=None, exclude=False):245 if suffix is None:246 suffix = self._get_include_exclude_suffix(exclude)247 return self.add_join(query_set, 'tko_test_attributes',248 join_key='test_idx',249 join_condition=join_condition,250 suffix=suffix, exclude=exclude)251 def _add_label_pivot_table_join(self, query_set, suffix, join_condition='',252 exclude=False, force_left_join=False):253 return self.add_join(query_set, 'tko_test_labels_tests',254 join_key='test_id',255 join_condition=join_condition,256 suffix=suffix, exclude=exclude,257 force_left_join=force_left_join)258 def _add_label_joins(self, query_set, suffix=''):259 query_set = self._add_label_pivot_table_join(260 query_set, suffix=suffix, force_left_join=True)261 # since we're not joining from the original table, we can't use262 # self.add_join() again263 second_join_alias = 'tko_test_labels' + suffix264 second_join_condition = ('%s.id = %s.testlabel_id' %265 (second_join_alias,266 'tko_test_labels_tests' + suffix))267 query_set.query.add_custom_join('tko_test_labels',268 second_join_condition,269 query_set.query.LOUTER,270 alias=second_join_alias)271 return query_set272 def _get_label_ids_from_names(self, label_names):273 label_ids = list( # listifying avoids a double query below274 TestLabel.objects.filter(name__in=label_names)275 .values_list('name', 'id'))276 if len(label_ids) < len(set(label_names)):277 raise ValueError('Not all labels found: %s' %278 ', '.join(label_names))279 return dict(name_and_id for name_and_id in label_ids)280 def _include_or_exclude_labels(self, query_set, label_names, exclude=False):281 label_ids = self._get_label_ids_from_names(label_names).itervalues()282 suffix = self._get_include_exclude_suffix(exclude)283 condition = ('tko_test_labels_tests%s.testlabel_id IN (%s)' %284 (suffix,285 ','.join(str(label_id) for label_id in label_ids)))286 return self._add_label_pivot_table_join(query_set,287 join_condition=condition,288 suffix=suffix,289 exclude=exclude)290 def _add_custom_select(self, query_set, select_name, select_sql):291 return query_set.extra(select={select_name: select_sql})292 def _add_select_value(self, query_set, alias):293 return self._add_custom_select(query_set, alias,294 _quote_name(alias) + '.value')295 def _add_select_ifnull(self, query_set, alias, non_null_value):296 select_sql = "IF(%s.id IS NOT NULL, '%s', NULL)" % (_quote_name(alias),297 non_null_value)298 return self._add_custom_select(query_set, alias, select_sql)299 def _join_test_label_column(self, query_set, label_name, label_id):300 alias = 'test_label_' + label_name301 label_query = TestLabel.objects.filter(name=label_name)302 query_set = Test.objects.join_custom_field(query_set, label_query,303 alias)304 query_set = self._add_select_ifnull(query_set, alias, label_name)305 return query_set306 def _join_test_label_columns(self, query_set, label_names):307 label_id_map = self._get_label_ids_from_names(label_names)308 for label_name in label_names:309 query_set = self._join_test_label_column(query_set, label_name,310 label_id_map[label_name])311 return query_set312 def _join_test_attribute(self, query_set, attribute, alias=None,313 extra_join_condition=None):314 """315 Join the given TestView QuerySet to TestAttribute. The resulting query316 has an additional column for the given attribute named317 "attribute_<attribute name>".318 """319 if not alias:320 alias = 'test_attribute_' + attribute321 attribute_query = TestAttribute.objects.filter(attribute=attribute)322 if extra_join_condition:323 attribute_query = attribute_query.extra(324 where=[extra_join_condition])325 query_set = Test.objects.join_custom_field(query_set, attribute_query,326 alias)327 query_set = self._add_select_value(query_set, alias)328 return query_set329 def _join_machine_label_columns(self, query_set, machine_label_names):330 for label_name in machine_label_names:331 alias = 'machine_label_' + label_name332 condition = "FIND_IN_SET('%s', %s)" % (333 label_name, _quote_name(alias) + '.value')334 query_set = self._join_test_attribute(335 query_set, 'host-labels',336 alias=alias, extra_join_condition=condition)337 query_set = self._add_select_ifnull(query_set, alias, label_name)338 return query_set339 def _join_one_iteration_key(self, query_set, result_key, first_alias=None):340 alias = 'iteration_result_' + result_key341 iteration_query = IterationResult.objects.filter(attribute=result_key)342 if first_alias:343 # after the first join, we need to match up iteration indices,344 # otherwise each join will expand the query by the number of345 # iterations and we'll have extraneous rows346 iteration_query = iteration_query.extra(347 where=['%s.iteration = %s.iteration'348 % (_quote_name(alias), _quote_name(first_alias))])349 query_set = Test.objects.join_custom_field(query_set, iteration_query,350 alias, left_join=False)351 # select the iteration value and index for this join352 query_set = self._add_select_value(query_set, alias)353 if not first_alias:354 # for first join, add iteration index select too355 query_set = self._add_custom_select(356 query_set, 'iteration_index',357 _quote_name(alias) + '.iteration')358 return query_set, alias359 def _join_iteration_results(self, test_view_query_set, result_keys):360 """Join the given TestView QuerySet to IterationResult for one result.361 The resulting query looks like a TestView query but has one row per362 iteration. Each row includes all the attributes of TestView, an363 attribute for each key in result_keys and an iteration_index attribute.364 We accomplish this by joining the TestView query to IterationResult365 once per result key. Each join is restricted on the result key (and on366 the test index, like all one-to-many joins). For the first join, this367 is the only restriction, so each TestView row expands to a row per368 iteration (per iteration that includes the key, of course). For each369 subsequent join, we also restrict the iteration index to match that of370 the initial join. This makes each subsequent join produce exactly one371 result row for each input row. (This assumes each iteration contains372 the same set of keys. Results are undefined if that's not true.)373 """374 if not result_keys:375 return test_view_query_set376 query_set, first_alias = self._join_one_iteration_key(377 test_view_query_set, result_keys[0])378 for result_key in result_keys[1:]:379 query_set, _ = self._join_one_iteration_key(query_set, result_key,380 first_alias=first_alias)381 return query_set382 def _join_job_keyvals(self, query_set, job_keyvals):383 for job_keyval in job_keyvals:384 alias = 'job_keyval_' + job_keyval385 keyval_query = JobKeyval.objects.filter(key=job_keyval)386 query_set = Job.objects.join_custom_field(query_set, keyval_query,387 alias)388 query_set = self._add_select_value(query_set, alias)389 return query_set390 def _join_iteration_attributes(self, query_set, iteration_attributes):391 for attribute in iteration_attributes:392 alias = 'iteration_attribute_' + attribute393 attribute_query = IterationAttribute.objects.filter(394 attribute=attribute)395 query_set = Test.objects.join_custom_field(query_set,396 attribute_query, alias)397 query_set = self._add_select_value(query_set, alias)398 return query_set399 def get_query_set_with_joins(self, filter_data):400 """Add joins for querying over test-related items.401 These parameters are supported going forward:402 * test_attribute_fields: list of attribute names. Each attribute will403 be available as a column attribute_<name>.value.404 * test_label_fields: list of label names. Each label will be available405 as a column label_<name>.id, non-null iff the label is present.406 * iteration_result_fields: list of iteration result names. Each407 result will be available as a column iteration_<name>.value.408 Note that this changes the semantics to return iterations409 instead of tests -- if a test has multiple iterations, a row410 will be returned for each one. The iteration index is also411 available as iteration_<name>.iteration.412 * machine_label_fields: list of machine label names. Each will be413 available as a column machine_label_<name>.id, non-null iff the414 label is present on the machine used in the test.415 * job_keyval_fields: list of job keyval names. Each value will be416 available as a column job_keyval_<name>.id, non-null iff the417 keyval is present in the AFE job.418 * iteration_attribute_fields: list of iteration attribute names. Each419 attribute will be available as a column420 iteration_attribute<name>.id, non-null iff the attribute is421 present.422 These parameters are deprecated:423 * include_labels424 * exclude_labels425 * include_attributes_where426 * exclude_attributes_where427 Additionally, this method adds joins if the following strings are428 present in extra_where (this is also deprecated):429 * test_labels430 * test_attributes_host_labels431 @param filter_data: Data by which to filter.432 @return A QuerySet.433 """434 query_set = self.get_query_set()435 test_attributes = filter_data.pop('test_attribute_fields', [])436 for attribute in test_attributes:437 query_set = self._join_test_attribute(query_set, attribute)438 test_labels = filter_data.pop('test_label_fields', [])439 query_set = self._join_test_label_columns(query_set, test_labels)440 machine_labels = filter_data.pop('machine_label_fields', [])441 query_set = self._join_machine_label_columns(query_set, machine_labels)442 iteration_keys = filter_data.pop('iteration_result_fields', [])443 query_set = self._join_iteration_results(query_set, iteration_keys)444 job_keyvals = filter_data.pop('job_keyval_fields', [])445 query_set = self._join_job_keyvals(query_set, job_keyvals)446 iteration_attributes = filter_data.pop('iteration_attribute_fields', [])447 query_set = self._join_iteration_attributes(query_set,448 iteration_attributes)449 # everything that follows is deprecated behavior450 joined = False451 extra_where = filter_data.get('extra_where', '')452 if 'tko_test_labels' in extra_where:453 query_set = self._add_label_joins(query_set)454 joined = True455 include_labels = filter_data.pop('include_labels', [])456 exclude_labels = filter_data.pop('exclude_labels', [])457 if include_labels:458 query_set = self._include_or_exclude_labels(query_set,459 include_labels)460 joined = True461 if exclude_labels:462 query_set = self._include_or_exclude_labels(query_set,463 exclude_labels,464 exclude=True)465 joined = True466 include_attributes_where = filter_data.pop('include_attributes_where',467 '')468 exclude_attributes_where = filter_data.pop('exclude_attributes_where',469 '')470 if include_attributes_where:471 query_set = self._add_attribute_join(472 query_set,473 join_condition=self.escape_user_sql(include_attributes_where))474 joined = True475 if exclude_attributes_where:476 query_set = self._add_attribute_join(477 query_set,478 join_condition=self.escape_user_sql(exclude_attributes_where),479 exclude=True)480 joined = True481 if not joined:482 filter_data['no_distinct'] = True483 if 'tko_test_attributes_host_labels' in extra_where:484 query_set = self._add_attribute_join(485 query_set, suffix='_host_labels',486 join_condition='tko_test_attributes_host_labels.attribute = '487 '"host-labels"')488 return query_set489 def query_test_ids(self, filter_data, apply_presentation=True):490 """Queries for test IDs.491 @param filter_data: Data by which to filter.492 @param apply_presentation: Whether or not to apply presentation493 parameters.494 @return A list of test IDs.495 """496 query = self.model.query_objects(filter_data,497 apply_presentation=apply_presentation)498 dicts = query.values('test_idx')499 return [item['test_idx'] for item in dicts]500 def query_test_label_ids(self, filter_data):501 """Queries for test label IDs.502 @param filter_data: Data by which to filter.503 @return A list of test label IDs.504 """505 query_set = self.model.query_objects(filter_data)506 query_set = self._add_label_joins(query_set, suffix='_list')507 rows = self._custom_select_query(query_set, ['tko_test_labels_list.id'])508 return [row[0] for row in rows if row[0] is not None]509 def escape_user_sql(self, sql):510 sql = super(TestViewManager, self).escape_user_sql(sql)511 return sql.replace('test_idx', self.get_key_on_this_table('test_idx'))512class TestView(dbmodels.Model, model_logic.ModelExtensions):513 """Models a test view."""514 extra_fields = {515 'DATE(job_queued_time)': 'job queued day',516 'DATE(test_finished_time)': 'test finished day',517 }518 group_fields = [519 'test_name',520 'status',521 'kernel',522 'hostname',523 'job_tag',524 'job_name',525 'platform',526 'reason',527 'job_owner',528 'job_queued_time',529 'DATE(job_queued_time)',530 'test_started_time',531 'test_finished_time',532 'DATE(test_finished_time)',533 ]534 test_idx = dbmodels.IntegerField('test index', primary_key=True)535 job_idx = dbmodels.IntegerField('job index', null=True, blank=True)536 test_name = dbmodels.CharField(blank=True, max_length=90)537 subdir = dbmodels.CharField('subdirectory', blank=True, max_length=180)538 kernel_idx = dbmodels.IntegerField('kernel index')539 status_idx = dbmodels.IntegerField('status index')540 reason = dbmodels.CharField(blank=True, max_length=3072)541 machine_idx = dbmodels.IntegerField('host index')542 test_started_time = dbmodels.DateTimeField(null=True, blank=True)543 test_finished_time = dbmodels.DateTimeField(null=True, blank=True)544 job_tag = dbmodels.CharField(blank=True, max_length=300)545 job_name = dbmodels.CharField(blank=True, max_length=300)546 job_owner = dbmodels.CharField('owner', blank=True, max_length=240)547 job_queued_time = dbmodels.DateTimeField(null=True, blank=True)548 job_started_time = dbmodels.DateTimeField(null=True, blank=True)549 job_finished_time = dbmodels.DateTimeField(null=True, blank=True)550 afe_job_id = dbmodels.IntegerField(null=True)551 hostname = dbmodels.CharField(blank=True, max_length=300)552 platform = dbmodels.CharField(blank=True, max_length=240)553 machine_owner = dbmodels.CharField(blank=True, max_length=240)554 kernel_hash = dbmodels.CharField(blank=True, max_length=105)555 kernel_base = dbmodels.CharField(blank=True, max_length=90)556 kernel = dbmodels.CharField(blank=True, max_length=300)557 status = dbmodels.CharField(blank=True, max_length=30)558 invalid = dbmodels.BooleanField(blank=True)559 invalidates_test_idx = dbmodels.IntegerField(null=True, blank=True)560 objects = TestViewManager()561 def save(self):562 raise NotImplementedError('TestView is read-only')563 def delete(self):564 raise NotImplementedError('TestView is read-only')565 @classmethod566 def query_objects(cls, filter_data, initial_query=None,567 apply_presentation=True):568 if initial_query is None:569 initial_query = cls.objects.get_query_set_with_joins(filter_data)570 return super(TestView, cls).query_objects(571 filter_data, initial_query=initial_query,572 apply_presentation=apply_presentation)573 class Meta:574 """Metadata for class TestView."""...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run autotest automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful