Best Python code snippet using avocado_python
annotations_test.py
Source:annotations_test.py  
1#!/usr/bin/env python2from anti_instagram import logger, wrap_test_main3from anti_instagram.AntiInstagram import ScaleAndShift, calculate_transform4from duckietown_utils.expand_variables import expand_environment5from duckietown_utils.jpg import (image_clip_255, image_cv_from_jpg_fn,6    make_images_grid)7from duckietown_utils.locate_files_impl import locate_files8from line_detector.line_detector_plot import drawLines9import cv210import numpy as np11import os12import scipy.io13import yaml14import shelve15import operator16import copy17from duckietown_utils.ipython_utils import ipython_if_guy18        19        20def merge_comparison_results(comparison_results,overall_results):21    if (comparison_results):22        if (not overall_results):23            r_vals={};24            # ipython_if_guy()25            for t in comparison_results['r_vals'].keys():26                r_vals[t]=np.array([],'float32')27            g_vals=copy.deepcopy(r_vals);28            b_vals=copy.deepcopy(r_vals);29            h_vals=copy.deepcopy(r_vals);30            s_vals=copy.deepcopy(r_vals);31            v_vals=copy.deepcopy(r_vals);32            overall_results={'average_abs_err':[],'total_pixels':0,'total_error':0,'total_regions':0,'r_vals':r_vals,'g_vals':g_vals,'b_vals':b_vals,'h_vals':h_vals,'s_vals':s_vals,'v_vals':v_vals}33            34        # ipython_if_guy()35        # max_idx,max_type=max(enumerate(comparison_results['r_vals'].keys()), key=operator.itemgetter(1))36        for t in comparison_results['r_vals'].keys():37            overall_results['r_vals'][t]=np.concatenate((overall_results['r_vals'][t],comparison_results['r_vals'][t]),0)38            overall_results['g_vals'][t]=np.concatenate((overall_results['g_vals'][t],comparison_results['g_vals'][t]),0)39            overall_results['b_vals'][t]=np.concatenate((overall_results['b_vals'][t],comparison_results['b_vals'][t]),0)40            overall_results['h_vals'][t]=np.concatenate((overall_results['h_vals'][t],comparison_results['h_vals'][t]),0)41            overall_results['s_vals'][t]=np.concatenate((overall_results['s_vals'][t],comparison_results['s_vals'][t]),0)42            overall_results['v_vals'][t]=np.concatenate((overall_results['v_vals'][t],comparison_results['v_vals'][t]),0)43        44        overall_results['total_error']=overall_results['total_error']+comparison_results['total_error']45        overall_results['total_pixels']=overall_results['total_pixels']+comparison_results['total_pixels']46        overall_results['total_regions']=overall_results['total_regions']+comparison_results['total_regions']47        48    return overall_results49def examine_dataset(dirname, out):50    logger.info(dirname)51    dirname = expand_environment(dirname)52    jpgs = locate_files(dirname, '*.jpg')53    mats = locate_files(dirname, '*.mat')54    logger.debug('I found %d jpgs and %d mats' % (len(jpgs), len(mats)))55    if len(jpgs) == 0:56        msg = 'Not enough jpgs.'57        raise ValueError(msg)58#     if len(mats) == 0:59#         msg = 'Not enough mats.'60#         raise ValueError(msg)61    first_jpg = sorted(jpgs)[0]62    logger.debug('Using jpg %r to learn transformation.' % first_jpg)63    first_jpg_image = image_cv_from_jpg_fn(first_jpg)64    success, health, parameters = calculate_transform(first_jpg_image)65    s = ""66    s += 'success: %s\n' % str(success)67    s += 'health: %s\n' % str(health)68    s += 'parameters: %s\n' % str(parameters)69    w = os.path.join(out, 'learned_transform.txt')70    with open(w, 'w') as f:71        f.write(s)72    logger.info(s)73    74    transform = ScaleAndShift(**parameters)75    76    config_dir = '${DUCKIETOWN_ROOT}/catkin_ws/src/duckietown/config/baseline/line_detector/line_detector_node/'77    config_dir = expand_environment(config_dir)78    configurations = locate_files(config_dir, '*.yaml')79    #logger.info('configurations: %r' % configurations)80    for j in jpgs:81        summaries =[]82        83        shape = (200, 160)84        interpolation = cv2.INTER_NEAREST85        86        87        bn = os.path.splitext(os.path.basename(j))[0]88        fn = os.path.join(out, '%s.all.png' % (bn))89        90        if os.path.exists(fn):91            logger.debug('Skipping because file exists: %r' % fn)92        else:93            for c in configurations:94                logger.info('Trying %r' % c)95                name = os.path.splitext(os.path.basename(c))[0]96                if name in ['oreo', 'myrtle', 'bad_lighting', '226-night']:97                    continue98                with open(c) as f:99                    stuff = yaml.load(f)100    101                if not 'detector' in stuff:102                    msg = 'Cannot find "detector" section in %r' % c103                    raise ValueError(msg)104    105                detector = stuff['detector']106                logger.info(detector)107                if not isinstance(detector, list) and len(detector) == 2:108                    raise ValueError(detector)109                110                from duckietown_utils.instantiate_utils import instantiate111                112                def LineDetectorClass():113                    return instantiate(detector[0], detector[1])114        115                s = run_detection(transform, j, out, shape=shape,116                                  interpolation=interpolation, name=name,117                                  LineDetectorClass=LineDetectorClass)118                summaries.append(s)119            120            together = make_images_grid(summaries, cols=1, pad=10, bgcolor=[.5, .5, .5])121            cv2.imwrite(fn, zoom_image(together, 4))122    # ipython_if_guy()123    overall_results=[]124    comparison_results={}125    for m in mats:126        logger.debug(m)127        jpg = os.path.splitext(m)[0] + '.jpg'128        if not os.path.exists(jpg):129            msg = 'JPG %r for mat %r does not exist' % (jpg, m)130            logger.error(msg)131        else:132            frame_results=test_pair(transform, jpg, m, out)133            comparison_results[m]=frame_results134            overall_results=merge_comparison_results(comparison_results[m],overall_results)135            print "comparison_results[m]=frame_results"136            # ipython_if_guy()137    print "finished mats: "+dirname138    return overall_results139        140def zoom_image(im, zoom):141    zoom = 4142    s = (im.shape[1] * zoom, im.shape[0] * zoom)143    imz = cv2.resize(im, s, interpolation=cv2.INTER_NEAREST)144    return imz145def run_detection(transform, jpg, out, shape, interpolation,146                  name, LineDetectorClass):147    image = image_cv_from_jpg_fn(jpg)148    image = cv2.resize(image, shape, interpolation=interpolation)149    150    151#     bgr = bgr[bgr.shape[0] / 2:, :, :]152    image_detections = line_detection(LineDetectorClass, image)153    transformed = transform(image)154    transformed_clipped = image_clip_255(transformed)155    transformed_detections = line_detection(LineDetectorClass, transformed_clipped)156    if not os.path.exists(out):157        os.makedirs(out)158    bn = os.path.splitext(os.path.basename(jpg))[0]159    def write(postfix, im):160        fn = os.path.join(out, '%s.%s.%s.png' % (bn, name, postfix))161        cv2.imwrite(fn, zoom_image(im, 4))162    together = make_images_grid([image,  # transformed,163                                 merge_masks_res(image_detections),164                                 gray2rgb(image_detections['edges']),165                                 image_detections['annotated'],166                                 167                                 transformed_clipped,168                                 merge_masks_res(transformed_detections),169                                 gray2rgb(transformed_detections['edges']),170                                 transformed_detections['annotated'],171                       ], 172                                173                                cols=4, pad=35, bgcolor=[1, 1, 1])174    175    # write the string "name" in the upper left of image together176    cv2.putText(together, name, (0, 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)177    return together178def merge_masks_res(res):179    return merge_masks(res['area_white'], res['area_red'], res['area_yellow'])180def merge_masks(area_white, area_red, area_yellow):181    B, G, R = 0, 1, 2182    def white(x):183        x = gray2rgb(x)184        return x185    def red(x):186        x = gray2rgb(x)187        x[:,:,R] *= 1188        x[:,:,G] *= 0189        x[:,:,B] *= 0190        return x191    def yellow(x):192        x = gray2rgb(x)193        x[:,:,R] *= 1194        x[:,:,G] *= 1195        x[:,:,B] *= 0196        return x197    h, w = area_white.shape198    orig = [area_white, area_red, area_yellow]199    masks = [white(area_white), red(area_red), yellow(area_yellow)]200        201    res = np.zeros(shape=masks[0].shape, dtype=np.uint8)202    203    for i, m in enumerate(masks):204        nz = (orig[i] > 0) * 1.0205        assert nz.shape == (h, w), nz.shape206        207        for j in [0, 1, 2]:208            res[:,:,j] = (1-nz) * res[:,:,j].copy() + (nz) * m[:,:,j]209    210    return res211    212def test_pair(transform, jpg, mat, out):213    """ 214        jpg = filename215        mat = filename216    """217    data = scipy.io.loadmat(mat)218    regions = data['regions'].flatten()219    max_type=0;220    for r in regions:221        max_type=max(max_type,r['type'][0][0][0][0])222    r_vals={};223    for t in np.arange(max_type):224        r_vals[t+1]=np.array([],'float32')225    g_vals=copy.deepcopy(r_vals);226    b_vals=copy.deepcopy(r_vals);227    h_vals=copy.deepcopy(r_vals);228    s_vals=copy.deepcopy(r_vals);229    v_vals=copy.deepcopy(r_vals);230    result_stats={'average_abs_err':[],'total_pixels':0,'total_error':0,'total_regions':0,'r_vals':r_vals,'g_vals':g_vals,'b_vals':b_vals,'h_vals':h_vals,'s_vals':s_vals,'v_vals':v_vals}231    for r in regions:232        logger.info('region')233        x = r['x'][0][0].flatten()234        y = r['y'][0][0].flatten()235        mask = r['mask'][0][0]236        mask3=cv2.merge([mask,mask,mask])237        print 'x', x238        print 'y', y239        print 'mask shape', mask.shape240        print 'type', r['type'][0][0][0][0] # type in 1- based / matlab-based indices from the list of region types (i.e road, white, yellow, red, or what ever types were annotated) 241        print 'color', r['color'][0] # color in [r,g,b] where [r,g,b]are between 0 and 1242        t=r['type'][0][0][0][0];243        # print 'guy look here'244        region_color=r['color'][0];region_color=region_color[0][0]245        rval=region_color[0]*255.;246        gval=region_color[1]*255.;247        bval=region_color[2]*255.;248        image = image_cv_from_jpg_fn(jpg)249        transformed = transform(image)250        [b2,g2,r2]=cv2.split(transformed)251        thsv=cv2.cvtColor(transformed,cv2.cv.CV_BGR2HSV)252        [h2,s2,v2]=cv2.split(thsv)253        r2_=r2[mask.nonzero()];g2_=g2[mask.nonzero()];b2_=b2[mask.nonzero()]254        h2_=h2[mask.nonzero()];s2_=s2[mask.nonzero()];v2_=v2[mask.nonzero()]255        # ipython_if_guy()256        result_stats['r_vals'][t]=np.concatenate((result_stats['r_vals'][t],r2_),0)257        result_stats['g_vals'][t]=np.concatenate((result_stats['g_vals'][t],g2_),0)258        result_stats['b_vals'][t]=np.concatenate((result_stats['b_vals'][t],b2_),0)259        result_stats['h_vals'][t]=np.concatenate((result_stats['h_vals'][t],h2_),0)260        result_stats['s_vals'][t]=np.concatenate((result_stats['s_vals'][t],s2_),0)261        result_stats['v_vals'][t]=np.concatenate((result_stats['v_vals'][t],v2_),0)262        absdiff_img=cv2.absdiff(transformed,np.array([bval,gval,rval,0.]))263        masked_diff=cv2.multiply(np.array(absdiff_img,'float32'),np.array(mask3,'float32'))264        num_pixels=cv2.sumElems(mask)[0];265        region_error=cv2.sumElems(cv2.sumElems(masked_diff))[0];266        avg_abs_err=region_error/(num_pixels+1.);267        print 'Average abs. error', avg_abs_err268        result_stats['average_abs_err'].append(avg_abs_err)269        result_stats['total_pixels']=result_stats['total_pixels']+num_pixels270        result_stats['total_error']=result_stats['total_error']+region_error271        result_stats['total_regions']=result_stats['total_regions']+1272        # XXX: to finish273    return result_stats274def line_detection(LineDetectorClass, bgr):275    detector = LineDetectorClass()276    detector.setImage(bgr)277    image_with_lines = bgr.copy()278    # detect lines and normals279    white = detector.detectLines('white')280    yellow = detector.detectLines('yellow')281    red = detector.detectLines('red')282    # draw lines283    drawLines(image_with_lines, white.lines, (0, 0, 0))284    drawLines(image_with_lines, yellow.lines, (255, 0, 0))285    drawLines(image_with_lines, red.lines, (0, 255, 0))286    287#     elif isinstance(detector, LineDetector2):288#         # detect lines and normals289#         lines_white, normals_white, centers_white, area_white = detector.detectLines2('white')290#         lines_yellow, normals_yellow, centers_yellow, area_yellow = detector.detectLines2('yellow')291#         lines_red, normals_red, centers_red, area_red = detector.detectLines2('red')292# 293#         # draw lines294#         drawLines(image_with_lines, lines_white, (0, 0, 0))295#         drawLines(image_with_lines, lines_yellow, (255, 0, 0))296#         drawLines(image_with_lines, lines_red, (0, 255, 0))297#     298        # draw normals299        #detector.drawNormals2(centers_white, normals_white, (0, 0, 0))300        #detector.drawNormals2(centers_yellow, normals_yellow, (255, 0, 0))301        #detector.drawNormals2(centers_red, normals_red, (0, 255, 0))302        303    res = {}304    res['annotated'] = image_with_lines305    res['area_white'] = white.area306    res['area_red'] = red.area307    res['area_yellow'] = yellow.area308    res['edges'] = detector.edges309    return res310#    cv2.imwrite('lines_with_normal.png', detector.getImage())311def gray2rgb(gray):312    ''' 313        Converts a H x W grayscale into a H x W x 3 RGB image 314        by replicating the gray channel over R,G,B. 315        316        :param gray: grayscale317        :type  gray: array[HxW](uint8),H>0,W>0318        319        :return: A RGB image in shades of gray.320        :rtype: array[HxWx3](uint8)321    '''322#    assert_gray_image(gray, 'input to gray2rgb')323    rgb = np.zeros((gray.shape[0], gray.shape[1], 3), dtype='uint8')324    for i in range(3):325        rgb[:, :, i] = gray326    return rgb327def anti_instagram_annotations_test():328    base = "${DUCKIETOWN_DATA}/phase3-misc-files/so1/"329    base = expand_environment(base)330    dirs = locate_files(base, '*.iids1', alsodirs=True)331    directory_results={}332    overall_results=[]333    if not dirs:334        raise ValueError('No IIDS1 directories')335    336    for d in dirs:337        import getpass338        uname = getpass.getuser()339        out = os.path.join(os.path.dirname(d), uname, os.path.basename(d) + '.v')340        if not os.path.exists(out):341            os.makedirs(out)342        results=examine_dataset(d, out)343        overall_results=merge_comparison_results(results,overall_results)344        directory_results[d]=results345    db=shelve.open('tests_results',flag='n')346    db['directory_results'] = directory_results347    db['overall_results'] = overall_results348    db.close()349    print("overall average error: %f"%(overall_results['total_error']/overall_results['total_pixels']))350    print("overall regions checked: %f"%(overall_results['total_regions']))351    for t in overall_results['v_vals'].keys():352        print("region %f: RGB %f,%f,%f, HSV %f,%f,%f" %(t,np.mean(overall_results['r_vals'][t]),np.mean(overall_results['g_vals'][t]),np.mean(overall_results['b_vals'][t]),np.mean(overall_results['h_vals'][t]),np.mean(overall_results['s_vals'][t]),np.mean(overall_results['v_vals'][t])))353        354    ipython_if_guy()355if __name__ == '__main__':...tasks_host.py
Source:tasks_host.py  
1# Copyright 2019 Google LLC2#3# Licensed under the Apache License, Version 2.0 (the "License");4# you may not use this file except in compliance with the License.5# You may obtain a copy of the License at6#7#      http://www.apache.org/licenses/LICENSE-2.08#9# Unless required by applicable law or agreed to in writing, software10# distributed under the License is distributed on an "AS IS" BASIS,11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12# See the License for the specific language governing permissions and13# limitations under the License.14"""Tasks host."""15import datetime16from google.protobuf import wrappers_pb217import grpc18import six19from clusterfuzz._internal.bot import testcase_manager20from clusterfuzz._internal.bot.tasks import corpus_pruning_task21from clusterfuzz._internal.bot.untrusted_runner import file_host22from clusterfuzz._internal.datastore import data_types23from clusterfuzz._internal.protos import untrusted_runner_pb224from clusterfuzz.fuzz import engine25from . import host26def _fuzz_target_to_proto(fuzz_target):27  """Convert fuzz_target to protobuf."""28  return untrusted_runner_pb2.FuzzTarget(29      engine=fuzz_target.engine,30      project=fuzz_target.project,31      binary=fuzz_target.binary,32  )33def do_corpus_pruning(context, last_execution_failed, revision):34  """Do corpus pruning on untrusted worker."""35  cross_pollinate_fuzzers = [36      untrusted_runner_pb2.CrossPollinateFuzzer(37          fuzz_target=_fuzz_target_to_proto(cpf.fuzz_target),38          backup_bucket_name=cpf.backup_bucket_name,39          corpus_engine_name=cpf.corpus_engine_name,40      ) for cpf in context.cross_pollinate_fuzzers41  ]42  request = untrusted_runner_pb2.PruneCorpusRequest(43      fuzz_target=_fuzz_target_to_proto(context.fuzz_target),44      cross_pollinate_fuzzers=cross_pollinate_fuzzers,45      last_execution_failed=last_execution_failed,46      revision=revision)47  response = host.stub().PruneCorpus(request)48  project_qualified_name = context.fuzz_target.project_qualified_name()49  today_date = datetime.datetime.utcnow().date()50  coverage_info = data_types.CoverageInformation(51      fuzzer=project_qualified_name, date=today_date)52  # Intentionally skip edge and function coverage values as those would come53  # from fuzzer coverage cron task (see src/go/server/cron/coverage.go).54  coverage_info.corpus_size_units = response.coverage_info.corpus_size_units55  coverage_info.corpus_size_bytes = response.coverage_info.corpus_size_bytes56  coverage_info.corpus_location = response.coverage_info.corpus_location57  coverage_info.corpus_backup_location = (58      response.coverage_info.corpus_backup_location)59  coverage_info.quarantine_size_units = (60      response.coverage_info.quarantine_size_units)61  coverage_info.quarantine_size_bytes = (62      response.coverage_info.quarantine_size_bytes)63  coverage_info.quarantine_location = response.coverage_info.quarantine_location64  crashes = [65      corpus_pruning_task.CorpusCrash(66          crash_state=crash.crash_state,67          crash_type=crash.crash_type,68          crash_address=crash.crash_address,69          crash_stacktrace=crash.crash_stacktrace,70          unit_path=crash.unit_path,71          security_flag=crash.security_flag,72      ) for crash in response.crashes73  ]74  result_stats = response.cross_pollination_stats75  pollination_stats = corpus_pruning_task.CrossPollinationStats(76      project_qualified_name=result_stats.project_qualified_name,77      method=result_stats.method,78      sources=result_stats.sources,79      tags=result_stats.tags,80      initial_corpus_size=result_stats.initial_corpus_size,81      corpus_size=result_stats.corpus_size,82      initial_edge_coverage=result_stats.initial_edge_coverage,83      edge_coverage=result_stats.edge_coverage,84      initial_feature_coverage=result_stats.initial_feature_coverage,85      feature_coverage=result_stats.feature_coverage)86  return corpus_pruning_task.CorpusPruningResult(87      coverage_info=coverage_info,88      crashes=crashes,89      fuzzer_binary_name=response.fuzzer_binary_name,90      revision=response.revision,91      cross_pollination_stats=pollination_stats)92def process_testcase(engine_name, tool_name, target_name, arguments,93                     testcase_path, output_path, timeout):94  """Process testcase on untrusted worker."""95  if tool_name == 'minimize':96    operation = untrusted_runner_pb2.ProcessTestcaseRequest.MINIMIZE97  else:98    operation = untrusted_runner_pb2.ProcessTestcaseRequest.CLEANSE99  rebased_testcase_path = file_host.rebase_to_worker_root(testcase_path)100  file_host.copy_file_to_worker(testcase_path, rebased_testcase_path)101  request = untrusted_runner_pb2.ProcessTestcaseRequest(102      engine=engine_name,103      operation=operation,104      target_name=target_name,105      arguments=arguments,106      testcase_path=file_host.rebase_to_worker_root(testcase_path),107      output_path=file_host.rebase_to_worker_root(output_path),108      timeout=timeout)109  response = host.stub().ProcessTestcase(request)110  rebased_output_path = file_host.rebase_to_worker_root(output_path)111  file_host.copy_file_from_worker(rebased_output_path, output_path)112  return engine.ReproduceResult(113      list(response.command), response.return_code, response.time_executed,114      response.output)115def _unpack_values(values):116  """Unpack protobuf values."""117  unpacked = {}118  for key, packed_value in six.iteritems(values):119    if packed_value.Is(wrappers_pb2.DoubleValue.DESCRIPTOR):120      value = wrappers_pb2.DoubleValue()121    elif packed_value.Is(wrappers_pb2.Int64Value.DESCRIPTOR):122      value = wrappers_pb2.Int64Value()123    elif packed_value.Is(wrappers_pb2.StringValue.DESCRIPTOR):124      value = wrappers_pb2.StringValue()125    else:126      raise ValueError('Unknown stat type for ' + key)127    packed_value.Unpack(value)128    unpacked[key] = value.value129  return unpacked130def engine_fuzz(engine_impl, target_name, sync_corpus_directory,131                testcase_directory):132  """Run engine fuzzer on untrusted worker."""133  request = untrusted_runner_pb2.EngineFuzzRequest(134      engine=engine_impl.name,135      target_name=target_name,136      sync_corpus_directory=file_host.rebase_to_worker_root(137          sync_corpus_directory),138      testcase_directory=file_host.rebase_to_worker_root(testcase_directory))139  response = host.stub().EngineFuzz(request)140  crashes = [141      engine.Crash(142          input_path=file_host.rebase_to_host_root(crash.input_path),143          stacktrace=crash.stacktrace,144          reproduce_args=crash.reproduce_args,145          crash_time=crash.crash_time) for crash in response.crashes146  ]147  unpacked_stats = _unpack_values(response.stats)148  unpacked_strategies = _unpack_values(response.strategies)149  result = engine.FuzzResult(150      logs=response.logs,151      command=list(response.command),152      crashes=crashes,153      stats=unpacked_stats,154      time_executed=response.time_executed)155  file_host.pull_testcases_from_worker()156  return result, dict(response.fuzzer_metadata), unpacked_strategies157def engine_reproduce(engine_impl, target_name, testcase_path, arguments,158                     timeout):159  """Run engine reproduce on untrusted worker."""160  rebased_testcase_path = file_host.rebase_to_worker_root(testcase_path)161  file_host.copy_file_to_worker(testcase_path, rebased_testcase_path)162  request = untrusted_runner_pb2.EngineReproduceRequest(163      engine=engine_impl.name,164      target_name=target_name,165      testcase_path=rebased_testcase_path,166      arguments=arguments,167      timeout=timeout)168  try:169    response = host.stub().EngineReproduce(request)170  except grpc.RpcError as e:171    if 'TargetNotFoundError' in repr(e):172      # Resurface the right exception.173      raise testcase_manager.TargetNotFoundError('Failed to find target ' +174                                                 target_name)175    raise176  return engine.ReproduceResult(177      list(response.command), response.return_code, response.time_executed,...GoogleSearchPageTest.py
Source:GoogleSearchPageTest.py  
...29            browser.load_page()30            browser.set_search_text(self.search_text)31            browser.click_search_button()32            # time.sleep(3)33            result = browser.get_result_stats()34        except Exception as err:35            self.write_log.error(err)36        finally:37            browser.close_page()38            return result39    def write_browser_performance_info(self, browser_name, result_stats):40        self.write_log.info(41            "Browser: {} | Searched text: \"{}\" | results_count: {} | Time (sec): {}".format(browser_name,42                                                                                                self.search_text,43                                                                                                result_stats.split()[44                                                                                                    1],45                                                                                                result_stats.split()[46                                                                                                    3][1:]))47    def run_on_chrome(self):...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!!
