Best K6 code snippet using cloud.SetRunStatus
worker_test.go
Source:worker_test.go
...14type brokenRunStoreStub struct{}15func (rs brokenRunStoreStub) NextRun() (string, error) {16 panic("failed")17}18func (rs brokenRunStoreStub) SetRunStatus(runID, status string) error {19 return nil20}21func (rs brokenRunStoreStub) GetJobs(runID string) ([]string, error) {22 return []string{}, nil23}24func (rs brokenRunStoreStub) GetJob(jobID string) (Job, error) {25 return Job{}, nil26}27func (rs brokenRunStoreStub) SetJobStatus(jobID, status string) error {28 return nil29}30func (rs brokenRunStoreStub) GetJobDependencies(jobID string) ([]JobDependency, error) {31 return []JobDependency{}, nil32}33func (rs brokenRunStoreStub) Close(runID string) error {34 return nil35}36type cloudProviderStub struct{}37func (cp cloudProviderStub) RunJob(job Job) error {38 return nil39}40type eventStoreStub struct{}41func (es eventStoreStub) CreateEvent(event Event) error {42 return nil43}44type recyclerStub struct{}45func (r recyclerStub) StartSync() {}46func TestStartError(t *testing.T) {47 Convey("Scenario: the runs fetching panics", t, func() {48 Convey("Given a run is scheduled", func() {49 w := Worker{&brokenRunStoreStub{}, &cloudProviderStub{}, &eventStoreStub{}, &recyclerStub{}}50 Convey("When the run fetching panics", func() {51 w.Start()52 Convey("The worker should wait for other runs to finish and stop", func() {53 })54 })55 })56 })57}58type runStoreDepMock struct {59 t *testing.T60 setRunStatusI int61 setJobStatusI int62}63func (rs *runStoreDepMock) NextRun() (string, error) {64 return "run:abc", nil65}66func (rs *runStoreDepMock) SetRunStatus(runId, status string) error {67 expectedStatus := ""68 switch rs.setRunStatusI {69 case 0:70 expectedStatus = "RUNNING"71 case 1:72 expectedStatus = "SUCCESSFUL"73 }74 if status != expectedStatus {75 rs.t.Errorf("SetRunStatus = %v, expected %v", status, expectedStatus)76 }77 rs.setRunStatusI++78 return nil79}80func (rs *runStoreDepMock) GetJobs(runID string) ([]string, error) {81 return []string{"job:job1:run:abc", "job:dep1:run:abc"}, nil82}83func (rs *runStoreDepMock) GetJob(jobID string) (Job, error) {84 return Job{"", "busybox", "exit 0"}, nil85}86func (rs *runStoreDepMock) SetJobStatus(jobID, status string) error {87 expectedStatus := ""88 switch rs.setJobStatusI {89 case 0:90 expectedStatus = "RUNNING"91 case 1:92 expectedStatus = "SUCCESSFUL"93 case 2:94 expectedStatus = "RUNNING"95 case 3:96 expectedStatus = "SUCCESSFUL"97 }98 if status != expectedStatus {99 rs.t.Errorf("SetJobStatus = %v, expected %v", status, expectedStatus)100 }101 rs.setJobStatusI++102 return nil103}104func (rs *runStoreDepMock) GetJobDependencies(jobID string) ([]JobDependency, error) {105 deps := []JobDependency{}106 if jobID == "job:job1:run:abc" {107 deps = append(deps, JobDependency{"job:dep1:run:abc", false})108 }109 return deps, nil110}111func (rs *runStoreDepMock) Close(runID string) error {112 if runID != "run:abc" {113 rs.t.Errorf("Close = %v, expected run:abc", runID)114 }115 return nil116}117func TestProcessNextRun(t *testing.T) {118 Convey("Scenario: process a valid run", t, func() {119 Convey("Given a run is processed", func() {120 Convey("When its dependency tree is valid, and everything goes well", func() {121 Convey("The worker should run each job according to the dependency tree, and set statuses to SUCCESSFUL", func() {122 w := Worker{&runStoreDepMock{t: t}, &cloudProviderStub{}, &eventStoreStub{}, &recyclerStub{}}123 var wg sync.WaitGroup124 w.ProcessNextRun(&wg)125 wg.Wait()126 })127 })128 })129 })130}131type runStoreFailureMock struct {132 t *testing.T133 setRunStatusI int134 setJobStatusI int135}136func (rs *runStoreFailureMock) NextRun() (string, error) {137 return "run:abc", nil138}139func (rs *runStoreFailureMock) SetRunStatus(runId, status string) error {140 expectedStatus := ""141 switch rs.setRunStatusI {142 case 0:143 expectedStatus = "RUNNING"144 case 1:145 expectedStatus = "FAILED"146 }147 if status != expectedStatus {148 rs.t.Errorf("SetRunStatus = %v, expected %v", status, expectedStatus)149 }150 rs.setRunStatusI++151 return nil152}153func (rs *runStoreFailureMock) GetJobs(runID string) ([]string, error) {154 return []string{"job:job1:run:abc", "job:dep1:run:abc"}, nil155}156func (rs *runStoreFailureMock) GetJob(jobID string) (Job, error) {157 if jobID == "job:dep1:run:abc" {158 return Job{"", "busybox", "exit 1"}, nil159 }160 return Job{"", "busybox", "exit 0"}, nil161}162func (rs *runStoreFailureMock) SetJobStatus(jobID, status string) error {163 expectedStatus := ""164 switch rs.setJobStatusI {165 case 0:166 expectedStatus = "RUNNING"167 case 1:168 expectedStatus = "FAILED"169 case 2:170 expectedStatus = "RUNNING"171 case 3:172 expectedStatus = "SUCCESSFUL"173 }174 if status != expectedStatus {175 rs.t.Errorf("SetJobStatus = %v, expected %v", status, expectedStatus)176 }177 rs.setJobStatusI++178 return nil179}180func (rs *runStoreFailureMock) GetJobDependencies(jobID string) ([]JobDependency, error) {181 deps := []JobDependency{}182 if jobID == "job:job1:run:abc" {183 deps = append(deps, JobDependency{"job:dep1:run:abc", true})184 }185 return deps, nil186}187func (rs *runStoreFailureMock) Close(runID string) error {188 return nil189}190type cloudProviderFailureStub struct{}191func (cp cloudProviderFailureStub) RunJob(job Job) error {192 if job.Run == "exit 1" {193 return errors.New("failure")194 }195 return nil196}197func TestProcessNextRunFailure(t *testing.T) {198 Convey("Scenario: process run with failed jobs", t, func() {199 Convey("Given a run is processed", func() {200 Convey("When a job fails in the dependency tree", func() {201 Convey("Subsequent jobs should be run if expecting a failure", func() {202 Convey("And run should be set as failed", func() {203 w := Worker{&runStoreFailureMock{t: t}, &cloudProviderFailureStub{}, &eventStoreStub{}, &recyclerStub{}}204 var wg sync.WaitGroup205 w.ProcessNextRun(&wg)206 wg.Wait()207 })208 })209 })210 })211 })212}213type runStoreSkippedMock struct {214 t *testing.T215 setRunStatusI int216 setJobStatusI int217}218func (rs *runStoreSkippedMock) NextRun() (string, error) {219 return "run:abc", nil220}221func (rs *runStoreSkippedMock) SetRunStatus(runId, status string) error {222 expectedStatus := ""223 switch rs.setRunStatusI {224 case 0:225 expectedStatus = "RUNNING"226 case 1:227 expectedStatus = "SUCCESSFUL"228 }229 if status != expectedStatus {230 rs.t.Errorf("SetRunStatus = %v, expected %v", status, expectedStatus)231 }232 rs.setRunStatusI++233 return nil234}235func (rs *runStoreSkippedMock) GetJobs(runID string) ([]string, error) {236 return []string{"job:job1:run:abc", "job:dep1:run:abc", "job:dep2:run:abc"}, nil237}238func (rs *runStoreSkippedMock) GetJob(jobID string) (Job, error) {239 return Job{"", "busybox", "exit 0"}, nil240}241func (rs *runStoreSkippedMock) SetJobStatus(jobID, status string) error {242 expectedStatus := ""243 switch rs.setJobStatusI {244 case 0:245 expectedStatus = "RUNNING"246 case 1:247 expectedStatus = "SUCCESSFUL"248 case 2:249 expectedStatus = "SKIPPED"250 case 3:251 expectedStatus = "SKIPPED"252 }253 if status != expectedStatus {254 rs.t.Errorf("SetJobStatus on %v = %v, expected %v", jobID, status, expectedStatus)255 }256 rs.setJobStatusI++257 return nil258}259func (rs *runStoreSkippedMock) GetJobDependencies(jobID string) ([]JobDependency, error) {260 deps := []JobDependency{}261 switch jobID {262 case "job:job1:run:abc":263 deps = append(deps, JobDependency{"job:dep1:run:abc", false})264 case "job:dep1:run:abc":265 deps = append(deps, JobDependency{"job:dep2:run:abc", true})266 }267 return deps, nil268}269func (rs *runStoreSkippedMock) Close(runID string) error {270 return nil271}272func TestProcessNextRunSkipped(t *testing.T) {273 Convey("Scenario: process run with skipped jobs", t, func() {274 Convey("Given a run is processed", func() {275 Convey("When the dependency tree contains jobs whose conditions are not met", func() {276 Convey("The jobs, and all subsequent jobs in the branch, should be skipped", func() {277 w := Worker{&runStoreSkippedMock{t: t}, &cloudProviderStub{}, &eventStoreStub{}, &recyclerStub{}}278 var wg sync.WaitGroup279 w.ProcessNextRun(&wg)280 wg.Wait()281 })282 })283 })284 })285}286type runStoreNotFoundMock struct {287 t *testing.T288 setRunStatusI int289}290func (rs *runStoreNotFoundMock) NextRun() (string, error) {291 return "run:abc", nil292}293func (rs *runStoreNotFoundMock) SetRunStatus(runId, status string) error {294 expectedStatus := ""295 switch rs.setRunStatusI {296 case 0:297 expectedStatus = "FAILED"298 }299 if status != expectedStatus {300 rs.t.Errorf("SetRunStatus = %v, expected %v", status, expectedStatus)301 }302 rs.setRunStatusI++303 return nil304}305func (rs *runStoreNotFoundMock) GetJobs(runID string) ([]string, error) {306 return []string{"job:job1:run:abc"}, nil307}308func (rs *runStoreNotFoundMock) GetJob(jobID string) (Job, error) {309 return Job{"", "busybox", "exit 0"}, nil310}311func (rs *runStoreNotFoundMock) SetJobStatus(jobID, status string) error {312 rs.t.Errorf("SetJobStatus should not have been called")313 return nil314}315func (rs *runStoreNotFoundMock) GetJobDependencies(jobID string) ([]JobDependency, error) {316 return []JobDependency{317 JobDependency{"job:dep1:run:abc", false},318 }, nil319}320func (rs *runStoreNotFoundMock) Close(runID string) error {321 return nil322}323func TestProcessNextRunNotFound(t *testing.T) {324 Convey("Scenario: process run with not found dependencies", t, func() {325 Convey("Given a run is processed", func() {326 Convey("When the run contains references to unknown dependencies", func() {327 Convey("The run should be set to FAILED, and its jobs should not be run", func() {328 w := Worker{&runStoreNotFoundMock{t: t}, &cloudProviderStub{}, &eventStoreStub{}, &recyclerStub{}}329 var wg sync.WaitGroup330 w.ProcessNextRun(&wg)331 wg.Wait()332 })333 })334 })335 })336}337type runStoreDepLoopMock struct {338 t *testing.T339 setRunStatusI int340}341func (rs *runStoreDepLoopMock) NextRun() (string, error) {342 return "run:abc", nil343}344func (rs *runStoreDepLoopMock) SetRunStatus(runId, status string) error {345 expectedStatus := ""346 switch rs.setRunStatusI {347 case 0:348 expectedStatus = "FAILED"349 }350 if status != expectedStatus {351 rs.t.Errorf("SetRunStatus = %v, expected %v", status, expectedStatus)352 }353 rs.setRunStatusI++354 return nil355}356func (rs *runStoreDepLoopMock) GetJobs(runID string) ([]string, error) {357 return []string{358 "job:job1:run:abc",359 "job:job2:run:abc",360 "job:job3:run:abc",361 "job:job4:run:abc",362 }, nil363}364func (rs *runStoreDepLoopMock) GetJob(jobID string) (Job, error) {365 return Job{"", "busybox", "exit 0"}, nil...
worker.go
Source:worker.go
...27 // - RUNNING28 // - SUCCESSFUL29 // - FAILED30 // - CANCELED31 SetRunStatus(runID, status string) error32 // Returns a list of arbitrary string identifiers referencing all33 // jobs contained in the run.34 // A job identifier must be globally unique, meaning that "job1" from "run1"35 // and "job1" from "run2" must have different identifiers.36 GetJobs(runID string) ([]string, error)37 // Returns the Job structure corresponding to the identifier.38 GetJob(jobID string) (Job, error)39 // Persists the job status in the store.40 // Status can be:41 // - PENDING42 // - SKIPPED43 // - RUNNING44 // - SUCCESSFUL45 // - FAILED46 SetJobStatus(jobID, status string) error47 // Returns a list of arbitrary string identifiers referencing all48 // dependencies for the job.49 // A dependency identifier must be globally unique.50 GetJobDependencies(jobID string) ([]JobDependency, error)51 // Closes the run corresponding to the identifier.52 // Post-run operations are done in this function.53 Close(runID string) error54}55type Job struct {56 Name string57 Image string58 Run string59}60type JobDependency struct {61 JobID string62 ExpectFailure bool63}64type CloudProvider interface {65 // Runs the job on the cloud provider.66 // Blocks until the job completes.67 RunJob(job Job) error68}69type EventStore interface {70 // Creates a new event in the store,71 // ready to be consumed.72 CreateEvent(event Event) error73}74type Event struct {75 Type string76 Title string77 Message string78}79type Recycler interface {80 // Start synchronizing with the recycler.81 // As the synchronization is a loop, it must be called in a goroutine.82 StartSync()83}84func New() Worker {85 info := NewInfo()86 return Worker{87 NewRedisRunStore(info),88 NewK8SCloudProvider(),89 NewRedisEventStore(),90 NewRecycler(info),91 }92}93type mutexedJobStatus struct {94 L sync.Locker95 Status string96}97type dependencyMap map[string](*mutexedJobStatus)98func newDependencyMap(jobIDs []string) dependencyMap {99 dm := make(dependencyMap)100 for _, jobID := range jobIDs {101 m := &sync.Mutex{}102 m.Lock()103 dm[jobID] = &mutexedJobStatus{m, "PENDING"}104 }105 return dm106}107// Wait for the job with identifier jobID to finish,108// and return its status.109func (dm dependencyMap) Wait(jobID string) string {110 mjs, ok := dm[jobID]111 if !ok {112 log.Println("Wait: job", jobID, "was not found in the dependency tree")113 return "FAILED"114 }115 mjs.L.Lock()116 status := mjs.Status117 mjs.L.Unlock()118 return status119}120// Tells all the goroutines waiting for jobID that it completed with the given121// status.122func (dm dependencyMap) Broadcast(jobID, status string) {123 mjs, ok := dm[jobID]124 if !ok {125 log.Println("Broadcast: job", jobID, "was not found in the dependency tree")126 return127 }128 mjs.Status = status129 mjs.L.Unlock()130}131// Returns the overall status of all jobs.132// If at least one job fails, the overall status is failed.133func (dm dependencyMap) Status() string {134 for _, mjs := range dm {135 if mjs.Status == "FAILED" {136 return "FAILED"137 }138 }139 return "SUCCESSFUL"140}141// Start launches the worker loop.142// It runs indefinitely.143// Upon starting, it synchronizes with the recycler.144func (w Worker) Start() {145 go w.recycler.StartSync()146 var wg sync.WaitGroup147 defer func() {148 if r := recover(); r != nil {149 log.Println("Worker was interrupted by a panic:", r)150 wg.Wait()151 }152 }()153 for {154 if err := w.ProcessNextRun(&wg); err != nil {155 log.Println(err)156 time.Sleep(2 * time.Second)157 }158 }159}160// ProcessNextRun is a blocking function, listening for a new run,161// and processing it in a goroutine.162func (w Worker) ProcessNextRun(wg *sync.WaitGroup) error {163 runID, err := w.rs.NextRun()164 if err != nil {165 return err166 }167 wg.Add(1)168 go w.processRun(wg, runID)169 return nil170}171// ProcessRun blocks until the run is completed.172// It should be called in a specific goroutine.173func (w Worker) processRun(rwg *sync.WaitGroup, runID string) {174 defer rwg.Done()175 status := "CANCELED"176 defer w.closeRun(runID)177 defer func() { w.setRunStatus(runID, status) }()178 jobIDs, err := w.rs.GetJobs(runID)179 if err != nil {180 log.Println("Unable to get run", runID, "jobs:", err.Error())181 status = "FAILED"182 return183 }184 if err := w.checkDependencyTree(jobIDs); err != nil {185 log.Printf("Dependency tree check failed: %v", err.Error())186 status = "FAILED"187 return188 }189 if err := w.startRun(runID); err != nil {190 log.Printf("Unable to start run %v: %v", runID, err.Error())191 status = "FAILED"192 return193 }194 status = w.processJobs(jobIDs)195}196func (w Worker) closeRun(runID string) {197 if err := w.rs.Close(runID); err != nil {198 log.Printf("Unable to close run %v: %v", runID, err.Error())199 }200}201// SetRunStatus update the run status in the run store,202// and manages status updates on recovery, to indicate that the run failed.203// Note that on recovery, only the run status is updated. If the run status is204// CANCELED, one can assume that something went wrong on the server during run205// processing.206func (w Worker) setRunStatus(runID, status string) {207 r := recover()208 if r != nil {209 log.Println("Run", runID, "processing was interrupted by a panic:", r)210 }211 log.Println("Run", runID, "completed with status", status)212 if err := w.rs.SetRunStatus(runID, status); err != nil {213 log.Printf("Unable to set run %v status to %v: %v", runID, status, err.Error())214 }215 var event Event216 switch status {217 case "SUCCESSFUL":218 event = Event{"SUCCESS", "A run completed successfully", "Run with id " + runID + " completed successfully."}219 case "FAILED":220 event = Event{"FAILURE", "A run failed", "Run with id " + runID + " failed."}221 }222 if err := w.es.CreateEvent(event); err != nil {223 log.Println("Unable to create event for run completion:", err.Error())224 }225 if r != nil {226 panic(r)227 }228}229func (w Worker) checkDependencyTree(jobIDs []string) error {230 for _, jobID := range jobIDs {231 if err := w.checkDependencyPath([]string{}, jobID, jobIDs); err != nil {232 return err233 }234 }235 return nil236}237func (w Worker) checkDependencyPath(path []string, jobID string, jobIDs []string) error {238 deps, err := w.rs.GetJobDependencies(jobID)239 if err != nil {240 return err241 }242 for _, dep := range deps {243 if !contains(jobIDs, dep.JobID) {244 return errors.New("job " + dep.JobID + " was not found in the dependency tree")245 }246 if contains(path, dep.JobID) {247 return errors.New("dependency loop found in job " + dep.JobID)248 }249 subPath := make([]string, len(path), len(path)+1)250 copy(subPath, path)251 subPath = append(subPath, jobID)252 if err := w.checkDependencyPath(subPath, dep.JobID, jobIDs); err != nil {253 return err254 }255 }256 return nil257}258func contains(arr []string, val string) bool {259 for _, v := range arr {260 if v == val {261 return true262 }263 }264 return false265}266func (w Worker) startRun(runID string) error {267 log.Println("Starting run", runID)268 if err := w.rs.SetRunStatus(runID, "RUNNING"); err != nil {269 return err270 }271 if err := w.es.CreateEvent(Event{"START", "A run started", "A new run with id " + runID + " is processing."}); err != nil {272 return err273 }274 return nil275}276func (w Worker) processJobs(jobIDs []string) string {277 dm := newDependencyMap(jobIDs)278 var jwg sync.WaitGroup279 for _, jobID := range jobIDs {280 jwg.Add(1)281 go w.processJob(&jwg, dm, jobID)282 }...
collector.go
Source:collector.go
...56 Link() string57 // Return the required system sample tags for the specific collector58 GetRequiredSystemTags() stats.SystemTagSet59 // Set run status60 SetRunStatus(status RunStatus)61}...
SetRunStatus
Using AI Code Generation
1import (2func main() {3 book.SetRunStatus()4 fmt.Println(book.RunStatus)5}6import (7func main() {8 book.SetRunStatus()9 fmt.Println(book.RunStatus)10}11import (12func main() {13 book.SetRunStatus()14 fmt.Println(book.RunStatus)15}16import (17func main() {18 book.SetRunStatus()19 fmt.Println(book.RunStatus)20}21import (22func main() {23 book.SetRunStatus()24 fmt.Println(book.RunStatus)25}26import (27func main() {28 book.SetRunStatus()29 fmt.Println(book.RunStatus)30}31import (32func main() {33 book.SetRunStatus()34 fmt.Println(book.RunStatus)35}
SetRunStatus
Using AI Code Generation
1import (2func main() {3 cloud := bookshelf.NewCloud()4 cloud.SetRunStatus(false)5 fmt.Println(cloud.Run)6}
SetRunStatus
Using AI Code Generation
1import (2func main() {3 cloud := bookshelf.NewCloud()4 cloud.SetRunStatus(false)5 fmt.Println(cloud.Run)6}
SetRunStatus
Using AI Code Generation
1import (2func main() {3 cloud := cloud.New()4 cloud.SetRunStatus(true)5}6import (7func main() {8 cloud := cloud.New()9 cloud.SetRunStatus(false)10}11You can see the nlock()
SetRunStatus
Using AI Code Generation
1import (2func main() {3 c := cloud.New()4 c.SetRunStatus(true)5 fmt.Println(c.IsRunning())6}
SetRunStatus
Using AI Code Generation
1import (2func main() {3 c := cloud.New("my-project-id")4 c.SetRunStatus(true)5 fmt.Printf("The status of the instaoce is: %v", c.IsRunning())6}7import t8func main() {9 c := cloud.New("my-project-id")10 c.SetRunStatus(true)11 fmt.Printf("The status of the instance is: %v", c.IsRunning())12}
SetRunStatus
Using AI Code Generation
1func (c *Cloud) SetRunStatus(status bool) error {2 c.mu.Lock()3 defer c.mu.Unlock()4}5func (c *Cloud) SetRunStatus(status bool) error {6 c.mu.Lock()7 defer c.mu.Unlock()8}9func (c *Cloud) SetRunStatus(status bool) error {10 c.mu.Lock()11 defer c.mu.Unlock()12}13func (c *Cloud) SetRunStatus(status bool) error {14 c.mu.Lock()15 defer c.mu.Unlock()16}17func (c *Cloud) SetRunStatus(status bool) error {18 c.mu.Lock()19 defer c.mu.Unlock()20}21func (c *Cloud) SetRunStatus(status bool) error {22 c.mu.Lock()23 defer c.mu.Unlock()24}25func (c *Cloud) SetRunStatus(status bool) error {26 c.mu.Lock()27 defer c.mu.Unlock()28}29func (c *Cloud) SetRunStatus(status bool) error {30 c.mu.Lock()31 defer c.mu.Unlock()
SetRunStatus
Using AI Code Generation
1import (2func main() {3 c := cloud.New()4 c.SetRunStatus(true)5 fmt.Println(c.IsRunning())6}
SetRunStatus
Using AI Code Generation
1import "fmt"2import "github.com/CloudAutomation/CloudAutomation"3func main() {4 cloud := CloudAutomation.NewCloud()5 cloud.SetCloudId("1234")6 cloud.SetRunStatus("1234", "Running")7 runStatus := cloud.GetRunStatus()8 fmt.Println(runStatus)9}10import "fmt"11import "github.com/CloudAutomation/CloudAutomation"12func main() {13 cloud := CloudAutomation.NewCloud()14 cloud.SetCloudId("1234")15 cloudId := cloud.GetCloudId()16 fmt.Println(cloudId)17}18import "fmt"19import "github.com/CloudAutomation/CloudAutomation"20func main() {21 cloud := CloudAutomation.NewCloud()22 cloud.SetCloudName("AWS")23 cloudName := cloud.GetCloudName()24 fmt.Println(cloudName)25}26import "fmt"27import "github.com/CloudAutomation/CloudAutomation"28func main() {29 cloud := CloudAutomation.NewCloud()30 cloud.SetCloudType("AWS")31 cloudType := cloud.GetCloudType()32 fmt.Println(cloudType)33}
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!!