Best Python code snippet using ATX
xhdfs2.py
Source:xhdfs2.py
1#! /usr/local/bin/python32import os3import re4import sys5import atexit6import readline7import argparse8from subprocess import call, check_output9# TODO add alias support10# TODO wildcard support11# TODO multi version support12# TODO cron write history cmd file support13class Watcher:14 def path_change(self, path):15 pass16class PathWatcher(Watcher):17 def __init__(self, cmd):18 self.__cmd = cmd19 self.__hdfs_choices_cached = {}20 readline.parse_and_bind("tab: complete")21 readline.set_completer(self.completer)22 readline.set_completer_delims(' /')23 self.__histfile = os.path.expandvars('${HOME}/.xhdfs_history')24 if os.path.exists(self.__histfile):25 readline.read_history_file(self.__histfile)26 atexit.register(self.__save_histfile)27 self.__local_choices = []28 self.__remote_choices = []29 self.__mk_remote_choices('/')30 self.__mk_local_choices(os.getcwd())31 def path_change(self, path):32 if app.is_hdfs_mode:33 self.__mk_remote_choices(path)34 else:35 self.__mk_local_choices(path)36 def choice_layout(self):37 if app.print_autocomp_words:38 if len(self.__local_choices) > 0:39 print('\n--->local')40 cnt = 041 for choice in self.__local_choices:42 cnt += 143 if cnt % 4 == 0:44 print()45 print(choice.rjust(35), end=' ')46 if len(self.__remote_choices) > 0:47 print('\n\n--->hdfs')48 cnt = 049 for choice in self.__remote_choices:50 cnt += 151 if cnt % 4 == 0:52 print()53 print(choice.rjust(35), end=' ')54 if len(self.__local_choices) > 0 or len(self.__remote_choices) > 0:55 print()56 def completer(self, text, state):57 try:58 words = []59 line = readline.get_line_buffer()60 line = [ele for ele in re.split(r'\s+', line) if ele != '']61 if len(line) == 1:62 words = self.__cmd.hdfscmd()63 elif len(line) > 1:64 line = line[-1]65 if line.find('/') == -1:66 words = app.watcher().__choices()67 else:68 if not line[-1].endswith('/'):69 line = os.path.dirname(line)70 local_path = os.path.join(os.getcwd(), line)71 if os.path.exists(local_path):72 lchoices = check_output(['ls', local_path]).decode('utf-8').split('\n')[:-1]73 words.extend(lchoices)74 # print(f'\n@lchoices: {lchoices}@')75 else:76 hdfs_path = os.path.join(app.path().cwd(), line)77 if hdfs_path in self.__hdfs_choices_cached.keys():78 words.extend(self.__hdfs_choices_cached[hdfs_path])79 else:80 rchoices = check_output(['hdfs', 'dfs', '-ls', hdfs_path]).decode('utf-8').split('\n')[1:-1]81 rchoices = [rch.split('/')[-1] for rch in rchoices]82 words.extend(rchoices)83 self.__hdfs_choices_cached[hdfs_path] = rchoices84 # print(f'\n@rchoices: {words}@')85 words = [word for word in words if word.startswith(text)]86 # print(f'\n@auto complete word: {words[state]}@')87 return words[state]88 except IndexError:89 # print('\n@out of range@')90 return None91 def __save_histfile(self):92 readline.write_history_file(self.__histfile)93 def __mk_local_choices(self, path):94 self.__local_choices = check_output(['ls', path]).decode('utf-8').split('\n')[:-1]95 def __mk_remote_choices(self, path):96 self.__remote_choices = check_output(['hdfs', 'dfs', '-ls', path]).decode('utf-8').split('\n')[1:-1]97 self.__remote_choices = [rch.split('/')[-1] for rch in self.__remote_choices]98 def __choices(self):99 if args.dyn_choices:100 lcwd, rcwd = app.path().dcwd()101 self.__mk_local_choices(lcwd)102 self.__mk_remote_choices(rcwd)103 return self.__local_choices + self.__remote_choices104class BasePath:105 def __init__(self, cwd, oldcwd):106 self.__cwd = None107 self.__oldcwd = None108 self.__watchers = []109 self.cwd = cwd110 self.oldcwd = oldcwd111 def add_watcher(self, watcher):112 self.__watchers.append(watcher)113 def dscribe(self, path):114 [watcher.path_change(path) for watcher in self.__watchers]115 @property116 def cwd(self):117 return self.__cwd118 @cwd.setter119 def cwd(self, val):120 if self.__cwd != val:121 self.dscribe(val)122 self.__cwd = val123 @property124 def oldcwd(self):125 return self.__oldcwd126 @oldcwd.setter127 def oldcwd(self, val):128 self.__oldcwd = val129class Path:130 def __init__(self):131 self.__local_path = Path.LocalPath(os.getcwd(), os.getcwd())132 self.__remote_path = Path.RemotePath('/', '/')133 self.__path = self.__remote_path134 class LocalPath(BasePath):135 def __init__(self, cwd, oldcwd):136 super().__init__(cwd, oldcwd)137 def cd(self, path):138 if 'cd' == path:139 self.oldcwd = self.cwd140 os.chdir(os.path.expandvars('${HOME}'))141 self.cwd = os.getcwd()142 elif path == '..':143 self.oldcwd = self.cwd144 os.chdir(os.pardir)145 self.cwd = os.getcwd()146 elif path == '-':147 os.chdir(self.oldcwd)148 self.oldcwd, self.cwd = self.cwd, self.oldcwd149 else:150 dst = Path.normalize(path, self.cwd)151 if os.path.exists(dst):152 os.chdir(dst)153 self.oldcwd = self.cwd154 self.cwd = dst155 else:156 print(f'cd: no such directory: {path}')157 class RemotePath(BasePath):158 def __init__(self, cwd, oldcwd):159 super().__init__(cwd, oldcwd)160 def cd(self, path):161 if 'cd' == path:162 self.oldcwd = self.cwd163 self.cwd = '/'164 elif path == '..':165 self.oldcwd = self.cwd166 self.cwd = os.path.dirname(self.cwd)167 elif path == '-':168 self.oldcwd, self.cwd = self.cwd, self.oldcwd169 else:170 dst = Path.normalize(path, self.cwd)171 if 0 == call(['hadoop', 'fs', '-test', '-d', dst]):172 self.oldcwd = self.cwd173 self.cwd = dst174 else:175 print(f'cd: no such directory: {path}')176 def mode(self, mode):177 if mode:178 self.__path = self.__remote_path179 else:180 self.__path = self.__local_path181 def add_watcher(self, awatcher):182 self.__local_path.add_watcher(awatcher)183 self.__remote_path.add_watcher(awatcher)184 def prompt(self):185 local_bname = Path.__basename(self.__local_path.cwd)186 remote_bname = Path.__basename(self.__remote_path.cwd)187 prompt = '>'188 cmd_mode_prompt = 'hdfs'189 if not app.is_hdfs_mode:190 prompt += '>>'191 cmd_mode_prompt = 'local'192 return f'\n[{cmd_mode_prompt}][{local_bname}:{remote_bname}]{prompt} '193 def cwd(self):194 return self.__path.cwd195 def dcwd(self):196 return self.__local_path.cwd, self.__remote_path.cwd197 def cd(self, path):198 self.__path.cd(path)199 @staticmethod200 def normalize(path, cwd):201 if not path.startswith('hdfs://'):202 path = os.path.join(cwd, path)203 path = os.path.normpath(path)204 return path205 @staticmethod206 def __basename(path: str):207 if len(path) > 0:208 if path != '/':209 if path.endswith('/'):210 path = os.path.basename(os.path.dirname(path))211 else:212 path = os.path.basename(path)213 else:214 path = '/'215 return path216class Command:217 def __init__(self):218 self.__CMD_PWD = 'pwd'219 self.__CMD_EXIT = 'exit'220 self.__CMD_LOG_PRINT = 'log-print'221 self.__CMD_PRINT = 'cmd-print'222 self.__CMD_HISTORY = 'history'223 self.__CMD_CD = 'cd'224 self.__CMD_HDFS_ADDR = 'hdfs-addr'225 self.__CMD_ALIAS = 'alias'226 self.__CMD_CAT = 'cat'227 self.__CMD_CP = 'cp'228 self.__CMD_CHMOD = 'chmod'229 self.__CMD_CHOWN = 'chown'230 self.__CMD_GET = 'get'231 self.__CMD_LS = 'ls'232 self.__CMD_LL = 'll'233 self.__CMD_LSR = 'lsr'234 self.__CMD_MKDIR = 'mkdir'235 self.__CMD_MV = 'mv'236 self.__CMD_PUT = 'put'237 self.__CMD_RM = 'rm'238 self.__CMD_RMR = 'rmr'239 self.__CMD_TAIL = 'tail'240 self.__CMD_TOUCH = 'touch'241 self.__CMD_USAGE = 'usage'242 self.__common_alias: dict[str, list[str]] = {243 self.__CMD_LSR: [self.__CMD_LS, '-R'],244 self.__CMD_RMR: [self.__CMD_RM, '-R']245 }246 self.__hdfs_alias: dict[str, list[str]] = {247 self.__CMD_LL: [self.__CMD_LS, '']248 }249 self.__local_alias: dict[str, list[str]] = {250 self.__CMD_LL: [self.__CMD_LS, '-l']251 }252 self.__cmd: list[str] = []253 self.__hdfscmd: list[str] = ['!']254 for attr in dir(self):255 if attr.__contains__('__CMD'):256 self.__hdfscmd.append(self.__getattribute__(attr))257 def hdfscmd(self):258 return self.__hdfscmd259 def parse(self, cmd):260 self.__cmd = re.split(r'\s+', cmd)261 self.__cmd = [ele for ele in self.__cmd if ele != '']262 if 0 == len(self.__cmd):263 return264 self.__handle_alias()265 cname = self.__cmd[0]266 if cname == self.__CMD_EXIT:267 sys.exit()268 elif cname == '!':269 app.is_hdfs_mode = not app.is_hdfs_mode270 elif cname == self.__CMD_PWD:271 print(os.path.normpath(app.path().cwd()))272 elif cname == self.__CMD_ALIAS:273 self.__alias()274 elif cname == self.__CMD_LOG_PRINT:275 app.print_autocomp_words = not app.print_autocomp_words276 elif cname == self.__CMD_PRINT:277 app.print_cmd = not app.print_cmd278 elif cname == self.__CMD_HISTORY:279 Command.__history()280 elif cname == self.__CMD_CD:281 app.path().cd(self.__cmd[-1])282 elif cname == self.__CMD_HDFS_ADDR:283 Command.__hdfs_addr()284 # system commands285 elif not app.is_hdfs_mode:286 self.__exec()287 # hdfs commands288 elif cname == self.__CMD_CAT:289 self.__cat()290 elif cname == self.__CMD_CP:291 self.__cp()292 elif cname == self.__CMD_CHMOD:293 self.__chmod()294 elif cname == self.__CMD_CHOWN:295 self.__chown()296 elif cname == self.__CMD_GET:297 self.__get()298 elif cname == self.__CMD_LS:299 self.__ls()300 elif cname == self.__CMD_MKDIR:301 self.__mkdir()302 elif cname == self.__CMD_MV:303 self.__mv()304 elif cname == self.__CMD_PUT:305 self.__put()306 elif cname == self.__CMD_RM:307 self.__rm()308 elif cname == self.__CMD_TAIL:309 self.__tail()310 elif cname == self.__CMD_TOUCH:311 self.__touch()312 elif cname == self.__CMD_USAGE:313 self.__usage()314 else:315 return self.__not_find_cmd()316 # commands implementation317 def __cat(self):318 # cat URI319 if self.__non_options() < 2:320 return321 lcwd, rcwd = app.path().dcwd()322 for i in range(1, len(self.__cmd)):323 if not self.__cmd[i].startswith('-'):324 self.__cmd[i] = Path.normalize(self.__cmd[i], rcwd)325 326 self.__exec()327 def __cp(self):328 # cp [-f] URI <dest>329 non_options = self.__non_options()330 if non_options < 2:331 return332 elif non_options == 2:333 self.__cmd.append(app.path().cwd())334 lcwd, rcwd = app.path().dcwd()335 for i in range(1, len(self.__cmd)):336 if not self.__cmd[i].startswith('-'):337 self.__cmd[i] = Path.normalize(self.__cmd[i], rcwd)338 self.__exec()339 def __chmod(self):340 # chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...341 if self.__non_options() < 3:342 return343 self.__cmd[-1] = Path.normalize(self.__cmd[-1], app.path().dcwd()[1])344 self.__exec()345 def __chown(self):346 # chown [-R] [OWNER][:[GROUP]] PATH...347 if self.__non_options() < 3:348 return349 self.__cmd[-1] = Path.normalize(self.__cmd[-1], app.path().dcwd()[1])350 self.__exec()351 def __get(self):352 # get [-f] URI353 if self.__non_options() < 2:354 return355 lcwd, rcwd = app.path().dcwd()356 for i in range(1, len(self.__cmd) - 1):357 if not self.__cmd[i].startswith('-'):358 self.__cmd[i] = Path.normalize(self.__cmd[i], rcwd)359 self.__cmd[-1] = Path.normalize(self.__cmd[-1], lcwd)360 self.__exec()361 def __ls(self):362 # ls [-d] [-h] [-R] [<path> ...]363 nopt = self.__non_options()364 if 1 == nopt:365 self.__cmd.append(app.path().dcwd()[1])366 lcwd, rcwd = app.path().dcwd()367 for i in range(1, len(self.__cmd)):368 if not self.__cmd[i].startswith('-'):369 self.__cmd[i] = Path.normalize(self.__cmd[i], rcwd)370 self.__exec()371 def __mkdir(self):372 # mkdir [-p] <paths>373 if self.__non_options() < 2:374 return375 if '-p' not in self.__cmd:376 self.__cmd.insert(1, '-p')377 lcwd, rcwd = app.path().dcwd()378 for i in range(1, len(self.__cmd)):379 if not self.__cmd[i].startswith('-'):380 self.__cmd[i] = Path.normalize(self.__cmd[i], rcwd)381 self.__exec()382 def __mv(self):383 # mv URI <dest>384 non_options = self.__non_options()385 if non_options < 2:386 return387 elif non_options == 2:388 self.__cmd.append(app.path().cwd())389 for i in range(1, len(self.__cmd)):390 if not self.__cmd[i].startswith('-'):391 self.__cmd[i] = Path.normalize(self.__cmd[i], app.path().cwd())392 self.__exec()393 def __put(self):394 # put [-f] [-p] [-l] [-d] <localsrc> <dst>395 non_options = self.__non_options()396 if non_options < 2:397 return398 elif non_options == 2:399 self.__cmd.append(app.path().cwd())400 lcwd, rcwd = app.path().dcwd()401 for i in range(1, len(self.__cmd) - 1):402 if not self.__cmd[i].startswith('-'):403 self.__cmd[i] = Path.normalize(self.__cmd[i], lcwd)404 self.__cmd[-1] = Path.normalize(self.__cmd[-1], rcwd)405 self.__exec()406 def __rm(self):407 # rm [-R] URI408 if self.__non_options() < 2:409 return410 lcwd, rcwd = app.path().dcwd()411 for i in range(1, len(self.__cmd)):412 if not self.__cmd[i].startswith('-'):413 self.__cmd[i] = Path.normalize(self.__cmd[i], rcwd)414 self.__exec()415 def __tail(self):416 # tail [-f] URI417 if self.__non_options() < 2:418 return419 self.__cmd[-1] = Path.normalize(self.__cmd[-1], app.path().cwd())420 self.__exec()421 def __touch(self):422 # touchz URI423 if self.__non_options() < 2:424 return425 self.__cmd[0] += 'z'426 lcwd, rcwd = app.path().dcwd()427 for i in range(1, len(self.__cmd)):428 if not self.__cmd[i].startswith('-'):429 self.__cmd[i] = Path.normalize(self.__cmd[i], rcwd)430 self.__exec()431 @staticmethod432 def __history():433 hist = os.path.expandvars('${HOME}/.xhdfs_history')434 if os.path.exists(hist):435 with open(hist) as f:436 for cmd in f.readlines():437 print(cmd, end='')438 def __usage(self):439 # usage command440 if self.__non_options() < 2:441 return442 self.__exec()443 def __exec(self):444 cmd = ' '.join(self.__cmd)445 if app.is_hdfs_mode:446 cmd = 'hdfs dfs -' + cmd447 if app.print_cmd:448 print(f'\033[1;32;47m{cmd}\033[0m')449 call(cmd, shell=True)450 def __non_options(self):451 return len([ele for ele in self.__cmd if not ele.startswith('-')])452 def __not_find_cmd(self):453 cmd = ''.join(self.__cmd)454 cmd = f'command not find: {cmd}'455 print(f'\033[1;32;47m{cmd}\033[0m')456 def __handle_alias(self):457 key = self.__cmd[0]458 if key in self.__common_alias.keys():459 self.__cmd[0] = self.__common_alias[key][0]460 options = self.__common_alias[key][1]461 if len(options) > 0:462 self.__cmd.insert(1, options)463 return464 if app.is_hdfs_mode and key in self.__hdfs_alias.keys():465 self.__cmd[0] = self.__hdfs_alias[key][0]466 options = self.__hdfs_alias[key][1]467 if len(options) > 0:468 self.__cmd.insert(1, options)469 elif key in self.__local_alias.keys():470 self.__cmd[0] = self.__local_alias[key][0]471 options = self.__local_alias[key][1]472 if len(options) > 0:473 self.__cmd.insert(1, options)474 @staticmethod475 def __hdfs_addr():476 if os.getenv('HADOOP_HOME'):477 core_site_file = os.path.join(os.environ['HADOOP_HOME'], 'etc/hadoop/core-site.xml')478 cmd = f'grep -B 2 -A 1 \'hdfs://\' {core_site_file}'479 if app.print_cmd:480 print(cmd)481 call(cmd, shell=True)482 else:483 print('HADOOP_HOME environment variable not set!')484 def __alias(self):485 # alias alia=cmd [-h|-l|-c] [-option1, ...]486 if len(self.__cmd) == 1:487 self.__print_alias()488 return489 what = re.fullmatch(r'(?P<alia>\w+)\s*='490 r'\s*(?P<cmd>\w+)(\s+-(?P<mode>[hlc]))?(?P<options>\s+-\w+)*', ' '.join(self.__cmd[1:]))491 if what:492 alia = what.group('alia')493 cmd = what.group('cmd')494 mode = what.group('mode')495 options = what.group('options').lstrip(' ')496 val = [cmd]497 if options:498 options = options.split(r'\s+')499 val += options500 if not mode or mode == 'h':501 self.__hdfs_alias[alia] = val502 elif mode == 'l':503 self.__local_alias[alia] = val504 elif mode == 'c':505 self.__common_alias[alia] = val506 def __print_alias(self):507 alias = self.__common_alias508 if app.is_hdfs_mode:509 alias.update(self.__hdfs_alias)510 else:511 alias.update(self.__local_alias)512 for k, v in alias.items():513 v = [i for i in v if len(i) > 0]514 print(f'alias {k}=' + ' '.join(v))515class Main:516 def main(self):517 while True:518 self.watcher().choice_layout()519 # cmd = input(self.path().prompt())520 print(f'\033[1;32;47m{self.path().prompt()}\033[0m', end='')521 self.__cmd.parse(input())522 def __init__(self):523 self.__hdfs = True524 self.print_cmd = args.cmd_print525 self.print_autocomp_words = args.log_print526 self.__cmd = Command()527 self.__path = Path()528 self.__addr = args.hdfs_address529 self.init()530 self.__watcher = PathWatcher(self.__cmd)531 self.__path.add_watcher(self.__watcher)532 def init(self):533 if self.__addr:534 if os.getenv('HADOOP_HOME'):535 core_site_file = os.path.join(os.environ['HADOOP_HOME'], 'etc/hadoop/core-site.xml')536 with open(core_site_file) as f:537 core_site_conf = f.readlines()538 for row, line in enumerate(core_site_conf):539 if line.find('hdfs://') != -1:540 core_site_conf[row] = ' ' * 8 + f'<value>hdfs://{self.__addr}</value>\n'541 break542 with open(core_site_file, 'w') as f:543 f.writelines(core_site_conf)544 else:545 print('HADOOP_HOME environment variable not set!')546 @property547 def is_hdfs_mode(self):548 return self.__hdfs549 @is_hdfs_mode.setter550 def is_hdfs_mode(self, val):551 self.__hdfs = val552 self.path().mode(val)553 def path(self):554 return self.__path555 def watcher(self):556 return self.__watcher557def parse_args():558 parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)559 parser.add_argument('-c', '--cmd-print', action='store_true', help='if print exec command')560 parser.add_argument('-l', '--log-print', action='store_true', help='if print auto completion candidate words')561 parser.add_argument('-s', '--hdfs-address', help='hdfs cluster address')562 parser.add_argument('-d', '--dyn-choices', action='store_true', help='if dynamic make choices')563 return parser.parse_args()564if __name__ == '__main__':565 try:566 args = parse_args()567 # print(args)568 app = Main()569 app.main()570 except (EOFError, KeyboardInterrupt):...
lcd.py
Source:lcd.py
1import RPi.GPIO as GPIO2import time3import os4GPIO.setmode(GPIO.BCM)5GPIO.setwarnings(False)6## note=after calling GPIO.cleanup() function all data on display will get erase.7## You cannot use __send_data(), __send() functions and any variables used8## in all functions of this library. The functions which available for user is9## Print(note that capital P),clear,shift,begin,setCursor,blinkCursorOn,10## blinkCursorOff and The variables which available for user is right and left11## which used to indicated direction for shift the display.thanks for using12## this library. for more details or query you can mail me at13## shubham@electro-passion.com 14class lcd:15 right=True16 left=False17 __cmd=False18 __data=True19 def __send_data(self,value,signal):20 GPIO.output(self.__RS,signal)21 self.__send(value>>4)22 self.__send(value)23 time.sleep(0.001) 24 25 def __send(self,val):26 self.__val=val27 for i in range (0,4):28 GPIO.output(self.__D[i],((self.__val>>i) & 0x01))29 GPIO.output(self.__EN,False)30 time.sleep(0.000001)31 GPIO.output(self.__EN,True)32 time.sleep(0.000001)33 GPIO.output(self.__EN,False)34 time.sleep(0.0001)35 def Print(self,text):36 self.__text=str(text)37 self.__length=len(self.__text)38 for i in range (0,self.__length):39 self.__a=ord(self.__text[i])40 self.__send_data(self.__a,self.__data)41 def clear(self):42 self.__send_data(0x01,self.__cmd)43 44 def setCursor(self,row,col):45 self.__col=col-146 self.__row=row47 if(self.__row==1):48 self.__pos=0x8049 if(self.__row==2):50 self.__pos=0xC051 self.__cursor=self.__pos+self.__col52 self.__send_data(self.__cursor,self.__cmd) 53 54 def begin(self,d4,d5,d6,d7,rs,en):55 self.__D=[d4,d5,d6,d7]56 self.__RS=rs57 self.__EN=en58 for i in range(0,4):59 GPIO.setup(self.__D[i],GPIO.OUT)60 GPIO.setup(self.__RS,GPIO.OUT)61 GPIO.setup(self.__EN,GPIO.OUT)62 time.sleep(0.050)63 self.__send_data(0x30,self.__cmd)##first try64 time.sleep(0.05)65 self.__send_data(0x30,self.__cmd)##sencond try66 time.sleep(0.05)67 self.__send_data(0x30,self.__cmd)##third try68 time.sleep(0.0015)69 self.__send_data(0x20,self.__cmd)##final go70 self.__send_data(0x28,self.__cmd)##select 4 bit, mode 2 lins ,5x7 font71 self.__send_data(0x01,self.__cmd)##clear screen72 self.__send_data(0x06,self.__cmd)##display ON73 self.__send_data(0x80,self.__cmd)## bring cursor to position 0 of line 174 self.__send_data(0x0C,self.__cmd)## turn display ON for cursor blinking75 def shift(self,direction,count):76 self.__direction=direction77 self.__count=count78 if(self.__direction==self.left):79 for i in range (0,self.__count):80 self.__send_data(0x18,self.__cmd)81 time.sleep(1)82 if(self.__direction==self.right):83 for i in range (0,self.__count):84 self.__send_data(0x1C,self.__cmd)85 time.sleep(1)86 def blinkCursorOn(self):87 self.__send_data(0x0F,self.__cmd)88 89 def blinkCursorOff(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!!