Best Python code snippet using stestr_python
list_tests_test.py
Source:list_tests_test.py
1# Copyright 2015 The Chromium Authors. All rights reserved.2# Use of this source code is governed by a BSD-style license that can be3# found in the LICENSE file.4from __future__ import print_function5from __future__ import division6from __future__ import absolute_import7import json8import unittest9import webapp210import webtest11from google.appengine.ext import ndb12from dashboard import list_tests13from dashboard.common import datastore_hooks14from dashboard.common import layered_cache15from dashboard.common import testing_common16from dashboard.common import utils17from dashboard.models import graph_data18from dashboard.models import sheriff19class ListTestsTest(testing_common.TestCase):20 def setUp(self):21 super(ListTestsTest, self).setUp()22 app = webapp2.WSGIApplication(23 [('/list_tests', list_tests.ListTestsHandler)])24 self.testapp = webtest.TestApp(app)25 datastore_hooks.InstallHooks()26 self.UnsetCurrentUser()27 testing_common.SetIsInternalUser('internal@chromium.org', True)28 testing_common.SetIsInternalUser('foo@chromium.org', False)29 def _AddSampleData(self):30 testing_common.AddTests(31 ['Chromium'],32 ['win7', 'mac'],33 {34 'dromaeo': {35 'dom': {},36 'jslib': {},37 },38 'scrolling': {39 'commit_time': {40 'www.alibaba.com': {},41 'www.yahoo.com': {},42 'www.cnn.com': {},43 },44 'commit_time_ref': {},45 },46 'really': {47 'nested': {48 'very': {49 'deeply': {50 'subtest': {}51 }52 },53 'very_very': {}54 }55 },56 })57 def testPost_GetTestsForTestPath_Selected_Invalid(self):58 self._AddSampleData()59 # Requesting an invalid test path should not throw 500 error, it should60 # silently ignore the requested invalid test path.61 response = self.testapp.post('/list_tests', {62 'type': 'test_path_dict',63 'test_path_dict': json.dumps({64 'Chromium/win7/scrolling/commit_time': ['commit_time_ref']}),65 'return_selected': '1'})66 expected = {'anyMissing': True, 'tests': []}67 self.assertEqual(expected, json.loads(response.body))68 def testGetSubTests_FetchAndCacheBehavior(self):69 self._AddSampleData()70 # Set the has_rows flag to true on two of the TestMetadata entities.71 for test_path in [72 'Chromium/win7/really/nested/very/deeply/subtest',73 'Chromium/win7/really/nested/very_very']:74 test = utils.TestKey(test_path).get()75 test.has_rows = True76 test.put()77 # A tree-structured dict of dicts is constructed, and the 'has_rows'78 # flag is set to true for two of these tests. These two tests and79 # their parents are all included in the result.80 response = self.testapp.post('/list_tests', {81 'type': 'sub_tests',82 'suite': 'really',83 'bots': 'Chromium/win7,Chromium/mac'})84 self.assertEqual('*', response.headers.get('Access-Control-Allow-Origin'))85 expected = {86 'nested': {87 'has_rows': False,88 'sub_tests': {89 'very': {90 'has_rows': False,91 'sub_tests': {92 'deeply': {93 'has_rows': False,94 'sub_tests': {95 'subtest': {96 'has_rows': True,97 'sub_tests': {}98 }99 }100 }101 }102 },103 'very_very': {104 'has_rows': True,105 'sub_tests': {}106 }107 }108 }109 }110 # The response should be as expected.111 self.assertEqual(expected, json.loads(response.body))112 # The cache should be set for the win7 bot with the expected response.113 self.assertEqual(expected, json.loads(layered_cache.Get(114 graph_data.LIST_TESTS_SUBTEST_CACHE_KEY % (115 'Chromium', 'win7', 'really'))))116 # Change mac subtests in cache. Should be merged with win7.117 mac_subtests = {118 'mactest': {119 'has_rows': False,120 'sub_tests': {121 'graph': {122 'has_rows': True,123 'sub_tests': {}124 }125 }126 }127 }128 layered_cache.Set(129 graph_data.LIST_TESTS_SUBTEST_CACHE_KEY % ('Chromium', 'mac', 'really'),130 json.dumps(mac_subtests))131 response = self.testapp.post('/list_tests', {132 'type': 'sub_tests',133 'suite': 'really',134 'bots': 'Chromium/win7,Chromium/mac'})135 self.assertEqual('*', response.headers.get('Access-Control-Allow-Origin'))136 expected.update(mac_subtests)137 self.assertEqual(expected, json.loads(response.body))138 def testGetSubTests_ReturnsOnlyNonDeprecatedTests(self):139 # Sub-tests with the same name may be deprecated on only one bot, and not140 # deprecated on another bot; only non-deprecated tests should be returned.141 self._AddSampleData()142 # Set the deprecated flag to True for one test on one platform.143 test = utils.TestKey('Chromium/mac/dromaeo/jslib').get()144 test.deprecated = True145 test.put()146 # Set the has_rows flag to true for all of the test entities.147 for test_path in [148 'Chromium/win7/dromaeo/dom',149 'Chromium/win7/dromaeo/jslib',150 'Chromium/mac/dromaeo/dom',151 'Chromium/mac/dromaeo/jslib']:152 test = utils.TestKey(test_path).get()153 test.has_rows = True154 test.put()155 # When a request is made for subtests for the platform wherein that a156 # subtest is deprecated, that subtest will not be listed.157 response = self.testapp.post('/list_tests', {158 'type': 'sub_tests',159 'suite': 'dromaeo',160 'bots': 'Chromium/mac'})161 self.assertEqual('*', response.headers.get('Access-Control-Allow-Origin'))162 expected = {163 'dom': {164 'has_rows': True,165 'sub_tests': {}166 },167 'jslib': {168 'has_rows': True,169 'sub_tests': {},170 'deprecated': True171 }172 }173 self.assertEqual(expected, json.loads(response.body))174 def testPost_GetTestsForTestPath_Selected_SomeInternal(self):175 self._AddSampleData()176 # Set has_rows on two subtests but internal_only on only one.177 test = graph_data.TestMetadata.get_by_id(178 'Chromium/win7/scrolling/commit_time/www.cnn.com')179 test.internal_only = True180 test.has_rows = True181 test.put()182 test = graph_data.TestMetadata.get_by_id(183 'Chromium/win7/scrolling/commit_time/www.yahoo.com')184 test.has_rows = True185 test.put()186 request = {187 'type': 'test_path_dict',188 'test_path_dict': json.dumps({189 'Chromium/win7/scrolling/commit_time': [190 'www.cnn.com', 'www.yahoo.com']}),191 'return_selected': '1',192 }193 self.SetCurrentUser('internal@chromium.org')194 response = self.testapp.post('/list_tests', request)195 expected = {196 'anyMissing': False,197 'tests': [198 'Chromium/win7/scrolling/commit_time/www.cnn.com',199 'Chromium/win7/scrolling/commit_time/www.yahoo.com',200 ],201 }202 self.assertEqual(expected, json.loads(response.body))203 self.SetCurrentUser('foo@chromium.org')204 response = self.testapp.post('/list_tests', request)205 expected = {206 'anyMissing': True,207 'tests': [208 'Chromium/win7/scrolling/commit_time/www.yahoo.com',209 ],210 }211 self.assertEqual(expected, json.loads(response.body))212 def testGetSubTests_InternalData_OnlyReturnedForAuthorizedUsers(self):213 # When the user has a an internal account, internal-only data is given.214 self.SetCurrentUser('internal@chromium.org')215 self._AddSampleData()216 # Set internal_only on a bot and top-level test.217 bot = ndb.Key('Master', 'Chromium', 'Bot', 'win7').get()218 bot.internal_only = True219 bot.put()220 test = graph_data.TestMetadata.get_by_id('Chromium/win7/dromaeo')221 test.internal_only = True222 test.put()223 # Set internal_only and has_rows to true on two subtests.224 for name in ['dom', 'jslib']:225 subtest = graph_data.TestMetadata.get_by_id(226 'Chromium/win7/dromaeo/%s' % name)227 subtest.internal_only = True228 subtest.has_rows = True229 subtest.put()230 # All of the internal-only tests are returned.231 response = self.testapp.post('/list_tests', {232 'type': 'sub_tests', 'suite': 'dromaeo', 'bots': 'Chromium/win7'})233 expected = {234 'dom': {235 'has_rows': True,236 'sub_tests': {}237 },238 'jslib': {239 'has_rows': True,240 'sub_tests': {}241 }242 }243 self.assertEqual(expected, json.loads(response.body))244 # After setting the user to another domain, an empty dict is returned.245 self.SetCurrentUser('foo@chromium.org')246 response = self.testapp.post('/list_tests', {247 'type': 'sub_tests', 'suite': 'dromaeo', 'bots': 'Chromium/win7'})248 self.assertEqual({}, json.loads(response.body))249 def testMergeSubTestsDict(self):250 a = {251 'foo': {252 'has_rows': True,253 'sub_tests': {'a': {'has_rows': True, 'sub_tests': {}}},254 },255 'bar': {256 'has_rows': False,257 'sub_tests': {258 'b': {259 'has_rows': False,260 'sub_tests': {261 'c': {262 'has_rows': False,263 'deprecated': True,264 'sub_tests': {},265 },266 },267 },268 },269 },270 }271 b = {272 'bar': {273 'has_rows': True,274 'sub_tests': {275 'b': {276 'has_rows': False,277 'sub_tests': {278 'c': {279 'has_rows': False,280 'sub_tests': {},281 },282 },283 },284 },285 },286 'baz': {'has_rows': False, 'sub_tests': {}},287 }288 self.assertEqual(289 {290 'foo': {291 'has_rows': True,292 'sub_tests': {'a': {'has_rows': True, 'sub_tests': {}}},293 },294 'bar': {295 'has_rows': True,296 'sub_tests': {297 'b': {298 'has_rows': False,299 'sub_tests': {300 'c': {'has_rows': False, 'sub_tests': {}},301 },302 },303 },304 },305 'baz': {'has_rows': False, 'sub_tests': {}},306 },307 list_tests._MergeSubTestsDict(a, b))308 def testSubTestsDict(self):309 paths = [310 ['a', 'b', 'c'],311 ['a', 'b', 'c'],312 ['a', 'b', 'd'],313 ]314 expected = {315 'a': {316 'has_rows': False,317 'sub_tests': {318 'b': {319 'has_rows': False,320 'sub_tests': {321 'c': {'has_rows': True, 'sub_tests': {}},322 'd': {'has_rows': True, 'sub_tests': {}},323 },324 },325 },326 },327 }328 self.assertEqual(329 expected, list_tests._SubTestsDict(paths, False))330 def testSubTestsDict_Deprecated(self):331 paths = [332 ['a'],333 ['a', 'b'],334 ]335 expected = {336 'a': {337 'has_rows': True,338 'deprecated': True,339 'sub_tests': {340 'b': {341 'has_rows': True,342 'deprecated': True,343 'sub_tests': {},344 },345 },346 },347 }348 self.assertEqual(349 expected, list_tests._SubTestsDict(paths, True))350 def testSubTestsDict_TopLevel_HasRows_False(self):351 paths = [352 ['a', 'b'],353 ['a', 'c'],354 ]355 expected = {356 'a': {357 'has_rows': False,358 'sub_tests': {359 'b': {'has_rows': True, 'sub_tests': {}},360 'c': {'has_rows': True, 'sub_tests': {}},361 },362 },363 }364 self.assertEqual(365 expected, list_tests._SubTestsDict(paths, False))366 def testSubTestsDict_RepeatedPathIgnored(self):367 paths = [368 ['a', 'b'],369 ['a', 'c'],370 ['a', 'b'],371 ]372 expected = {373 'a': {374 'has_rows': False,375 'sub_tests': {376 'b': {'has_rows': True, 'sub_tests': {}},377 'c': {'has_rows': True, 'sub_tests': {}},378 },379 },380 }381 self.assertEqual(382 expected, list_tests._SubTestsDict(paths, False))383 def testPost_GetTestsMatchingPattern(self):384 """Tests the basic functionality of the GetTestsMatchingPattern function."""385 self._AddSampleData()386 # A pattern can match tests with a particular bot and with a particular387 # number of levels of nesting.388 # The results are lexicographically ordered by test path.389 response = self.testapp.post('/list_tests', {390 'type': 'pattern',391 'p': 'Chromium/mac/*/*/www*'})392 expected = [393 'Chromium/mac/scrolling/commit_time/www.alibaba.com',394 'Chromium/mac/scrolling/commit_time/www.cnn.com',395 'Chromium/mac/scrolling/commit_time/www.yahoo.com',396 ]397 self.assertEqual(expected, json.loads(response.body))398 # The same thing is returned if has_rows is set to '0' or another string399 # that is not '1'.400 response = self.testapp.post('/list_tests', {401 'type': 'pattern',402 'has_rows': '0',403 'p': '*/mac/*/*/www*'})404 self.assertEqual(expected, json.loads(response.body))405 response = self.testapp.post('/list_tests', {406 'type': 'pattern',407 'has_rows': 'foo',408 'p': '*/mac/*/*/www*'})409 self.assertEqual(expected, json.loads(response.body))410 def testPost_GetTestsMatchingPattern_OnlyWithRows(self):411 """Tests GetTestsMatchingPattern with the parameter only_with_rows set."""412 self._AddSampleData()413 # When no TestMetadata entities have has_rows set, filtering with the414 # parameter 'has_rows' set to '1' results in no rows being returned.415 response = self.testapp.post('/list_tests', {416 'type': 'pattern',417 'has_rows': '1',418 'p': '*/mac/dromaeo/*'})419 self.assertEqual([], json.loads(response.body))420 # Set the has_rows flag on one of the tests.421 test = utils.TestKey('Chromium/mac/dromaeo/dom').get()422 test.has_rows = True423 test.put()424 # Even though multiple tests could match the pattern, only the test with425 # has_rows set is returned.426 response = self.testapp.post('/list_tests', {427 'type': 'pattern',428 'has_rows': '1',429 'p': '*/mac/dromaeo/*'})430 self.assertEqual(['Chromium/mac/dromaeo/dom'], json.loads(response.body))431 def testPost_GetTestsForTestPath_Selected_Core_MonitoredChildWithRows(self):432 yahoo_path = 'Chromium/win7/scrolling/commit_time/www.yahoo.com'433 sheriff.Sheriff(434 id='my_sheriff1', email='a@chromium.org', patterns=[yahoo_path]).put()435 self._AddSampleData()436 yahoo = graph_data.TestMetadata.get_by_id(yahoo_path)437 yahoo.has_rows = True438 yahoo.put()439 response = self.testapp.post('/list_tests', {440 'type': 'test_path_dict',441 'test_path_dict': json.dumps({442 'Chromium/win7/scrolling/commit_time': 'core'}),443 'return_selected': '1'})444 expected = {445 'anyMissing': False,446 'tests': ['Chromium/win7/scrolling/commit_time/www.yahoo.com'],447 }448 self.assertEqual(expected, json.loads(response.body))449 def testPost_GetTestsForTestPath_Selected_Core_MonitoredChildNoRows(self):450 self._AddSampleData()451 response = self.testapp.post('/list_tests', {452 'type': 'test_path_dict',453 'test_path_dict': json.dumps({454 'Chromium/win7/scrolling/commit_time': 'core'}),455 'return_selected': '1'})456 expected = {'tests': [], 'anyMissing': False}457 self.assertEqual(expected, json.loads(response.body))458 def testPost_GetTestsForTestPath_Selected_Core_ParentHasRows(self):459 self._AddSampleData()460 core = graph_data.TestMetadata.get_by_id(461 'Chromium/win7/scrolling/commit_time')462 core.has_rows = True463 core.put()464 response = self.testapp.post('/list_tests', {465 'type': 'test_path_dict',466 'test_path_dict': json.dumps({467 'Chromium/win7/scrolling/commit_time': 'core'}),468 'return_selected': '1'})469 expected = {470 'anyMissing': False,471 'tests': ['Chromium/win7/scrolling/commit_time'],472 }473 self.assertEqual(expected, json.loads(response.body))474 def testPost_GetTestsForTestPath_Selected_Core_AllHaveRows(self):475 yahoo_path = 'Chromium/win7/scrolling/commit_time/www.yahoo.com'476 sheriff.Sheriff(477 id='my_sheriff1', email='a@chromium.org', patterns=[yahoo_path]).put()478 self._AddSampleData()479 core = graph_data.TestMetadata.get_by_id(480 'Chromium/win7/scrolling/commit_time')481 core.has_rows = True482 core.put()483 yahoo = graph_data.TestMetadata.get_by_id(yahoo_path)484 yahoo.has_rows = True485 yahoo.put()486 response = self.testapp.post('/list_tests', {487 'type': 'test_path_dict',488 'test_path_dict': json.dumps({489 'Chromium/win7/scrolling/commit_time': 'core'}),490 'return_selected': '1'})491 expected = {492 'anyMissing': False,493 'tests': [494 'Chromium/win7/scrolling/commit_time',495 'Chromium/win7/scrolling/commit_time/www.yahoo.com',496 ],497 }498 self.assertEqual(expected, json.loads(response.body))499 def testPost_GetTestsForTestPath_Selected_Core_NoRows(self):500 self._AddSampleData()501 response = self.testapp.post('/list_tests', {502 'type': 'test_path_dict',503 'test_path_dict': json.dumps({504 'Chromium/win7/scrolling/commit_time': 'core'}),505 'return_selected': '1'})506 expected = {507 'anyMissing': False,508 'tests': [],509 }510 self.assertEqual(expected, json.loads(response.body))511 def testPost_GetTestsForTestPath_Selected_EmptyPreselected(self):512 self._AddSampleData()513 response = self.testapp.post('/list_tests', {514 'type': 'test_path_dict',515 'test_path_dict': json.dumps({516 'Chromium/win7/scrolling/commit_time': []}),517 'return_selected': '1'})518 expected = {'anyMissing': False, 'tests': []}519 self.assertEqual(expected, json.loads(response.body))520 def testPost_GetTestsForTestPath_Selected_Preselected(self):521 self._AddSampleData()522 test = utils.TestKey(523 'Chromium/win7/scrolling/commit_time/www.yahoo.com').get()524 test.has_rows = True525 test.put()526 response = self.testapp.post('/list_tests', {527 'type': 'test_path_dict',528 'test_path_dict': json.dumps({529 'Chromium/win7/scrolling/commit_time': [530 'commit_time', 'www.yahoo.com']}),531 'return_selected': '1'})532 expected = {533 'anyMissing': True,534 'tests': ['Chromium/win7/scrolling/commit_time/www.yahoo.com'],535 }536 self.assertEqual(expected, json.loads(response.body))537 def testPost_GetTestsForTestPath_Selected_Preselected_Multiple(self):538 self._AddSampleData()539 subtest = graph_data.TestMetadata.get_by_id(540 'Chromium/win7/scrolling/commit_time/www.cnn.com')541 subtest.has_rows = True542 subtest.put()543 subtest = graph_data.TestMetadata.get_by_id(544 'Chromium/mac/scrolling/commit_time/www.cnn.com')545 subtest.has_rows = True546 subtest.put()547 response = self.testapp.post('/list_tests', {548 'type': 'test_path_dict',549 'test_path_dict': json.dumps({550 'Chromium/win7/scrolling/commit_time': ['www.cnn.com'],551 'Chromium/mac/scrolling/commit_time': ['www.cnn.com']}),552 'return_selected': '1'})553 expected = {554 'anyMissing': False,555 'tests': [556 'Chromium/win7/scrolling/commit_time/www.cnn.com',557 'Chromium/mac/scrolling/commit_time/www.cnn.com'],558 }559 self.assertEqual(expected, json.loads(response.body))560 def testPost_GetTestsForTestPath_Selected_All(self):561 self._AddSampleData()562 subtest = graph_data.TestMetadata.get_by_id(563 'Chromium/win7/scrolling/commit_time/www.cnn.com')564 subtest.has_rows = True565 subtest.put()566 response = self.testapp.post('/list_tests', {567 'type': 'test_path_dict',568 'test_path_dict': json.dumps({569 'Chromium/win7/scrolling/commit_time': 'all'}),570 'return_selected': '1'})571 expected = {572 'anyMissing': True,573 'tests': ['Chromium/win7/scrolling/commit_time/www.cnn.com'],574 }575 self.assertEqual(expected, json.loads(response.body))576 def testPost_GetTestsForTestPath_Unselected_Core_NoParent(self):577 self._AddSampleData()578 response = self.testapp.post('/list_tests', {579 'type': 'test_path_dict',580 'test_path_dict': json.dumps({581 'Chromium/win7/scrolling/commit_time': 'core'}),582 'return_selected': '0'})583 expected = {'tests': []}584 self.assertEqual(expected, json.loads(response.body))585 def testPost_GetTestsForTestPath_Unselected_Core_Unmonitored(self):586 yahoo_path = 'Chromium/win7/scrolling/commit_time/www.yahoo.com'587 sheriff.Sheriff(588 id='my_sheriff1', email='a@chromium.org', patterns=[yahoo_path]).put()589 self._AddSampleData()590 cnn = graph_data.TestMetadata.get_by_id(591 'Chromium/win7/scrolling/commit_time/www.cnn.com')592 cnn.has_rows = True593 cnn.put()594 yahoo = graph_data.TestMetadata.get_by_id(yahoo_path)595 yahoo.has_rows = True596 yahoo.put()597 response = self.testapp.post('/list_tests', {598 'type': 'test_path_dict',599 'test_path_dict': json.dumps({600 'Chromium/win7/scrolling/commit_time': 'core'}),601 'return_selected': '0'})602 expected = {603 'tests': ['Chromium/win7/scrolling/commit_time/www.cnn.com'],604 }605 self.assertEqual(expected, json.loads(response.body))606 def testPost_GetTestsForTestPath_Unselected_EmptyPreselected(self):607 self._AddSampleData()608 response = self.testapp.post('/list_tests', {609 'type': 'test_path_dict',610 'test_path_dict': json.dumps({611 'Chromium/win7/scrolling/commit_time': []}),612 'return_selected': '0'})613 expected = {614 'tests': ['Chromium/win7/scrolling/commit_time'],615 }616 self.assertEqual(expected, json.loads(response.body))617 def testPost_GetTestsForTestPath_Unselected_PreselectedWithRows(self):618 self._AddSampleData()619 subtest = graph_data.TestMetadata.get_by_id(620 'Chromium/win7/scrolling/commit_time/www.cnn.com')621 subtest.has_rows = True622 subtest.put()623 response = self.testapp.post('/list_tests', {624 'type': 'test_path_dict',625 'test_path_dict': json.dumps({626 'Chromium/win7/scrolling/commit_time': [627 'commit_time', 'www.yahoo.com']}),628 'return_selected': '0'})629 expected = {630 'tests': ['Chromium/win7/scrolling/commit_time/www.cnn.com'],631 }632 self.assertEqual(expected, json.loads(response.body))633 def testPost_GetTestsForTestPath_Unselected_PreselectedWithoutRows(self):634 self._AddSampleData()635 response = self.testapp.post('/list_tests', {636 'type': 'test_path_dict',637 'test_path_dict': json.dumps({638 'Chromium/win7/scrolling/commit_time': [639 'commit_time', 'www.yahoo.com']}),640 'return_selected': '0'})641 expected = {'tests': []}642 self.assertEqual(expected, json.loads(response.body))643 def testPost_GetTestsForTestPath_Unselected_All(self):644 self._AddSampleData()645 response = self.testapp.post('/list_tests', {646 'type': 'test_path_dict',647 'test_path_dict': json.dumps({648 'Chromium/win7/scrolling/commit_time': 'all'}),649 'return_selected': '0'})650 self.assertEqual({'tests': []}, json.loads(response.body))651 def testGetDescendants(self):652 self._AddSampleData()653 self.assertEqual(654 list_tests.GetTestDescendants(655 ndb.Key('TestMetadata', 'Chromium/mac/dromaeo')), [656 ndb.Key('TestMetadata', 'Chromium/mac/dromaeo'),657 ndb.Key('TestMetadata', 'Chromium/mac/dromaeo/dom'),658 ndb.Key('TestMetadata', 'Chromium/mac/dromaeo/jslib'),])659 self.assertEqual(660 list_tests.GetTestDescendants(661 ndb.Key('TestMetadata', 'Chromium/win7/really/nested')), [662 ndb.Key('TestMetadata', 'Chromium/win7/really/nested'),663 ndb.Key('TestMetadata', 'Chromium/win7/really/nested/very'),664 ndb.Key('TestMetadata',665 'Chromium/win7/really/nested/very/deeply'),666 ndb.Key('TestMetadata',667 'Chromium/win7/really/nested/very/deeply/subtest'),668 ndb.Key('TestMetadata',669 'Chromium/win7/really/nested/very_very'),])670if __name__ == '__main__':...
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.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!