Best JavaScript code snippet using stryker-parent
4-mutation-test-executor.spec.ts
Source:4-mutation-test-executor.spec.ts
1import sinon from 'sinon';2import { expect } from 'chai';3import { testInjector, factory, tick } from '@stryker-mutator/test-helpers';4import { Reporter } from '@stryker-mutator/api/report';5import { TestRunner, MutantRunOptions, MutantRunResult, MutantRunStatus } from '@stryker-mutator/api/test-runner';6import { CheckResult, CheckStatus } from '@stryker-mutator/api/check';7import { mergeMap } from 'rxjs/operators';8import { Observable } from 'rxjs';9import { Mutant, MutantStatus, MutantTestCoverage, MutantEarlyResultPlan, MutantRunPlan, MutantTestPlan } from '@stryker-mutator/api/core';10import { I, Task } from '@stryker-mutator/util';11import { MutationTestExecutor } from '../../../src/process/index.js';12import { coreTokens } from '../../../src/di/index.js';13import { createTestRunnerPoolMock, createCheckerPoolMock } from '../../helpers/producers.js';14import { MutationTestReportHelper } from '../../../src/reporters/mutation-test-report-helper.js';15import { Timer } from '../../../src/utils/timer.js';16import { ConcurrencyTokenProvider, Pool } from '../../../src/concurrent/index.js';17import { Sandbox } from '../../../src/sandbox/index.js';18import { MutantTestPlanner } from '../../../src/mutants/index.js';19import { CheckerFacade } from '../../../src/checker/checker-facade.js';20function ignoredEarlyResultPlan(overrides?: Partial<Mutant>): MutantEarlyResultPlan {21 return factory.mutantEarlyResultPlan({22 mutant: { ...factory.mutant(overrides), status: MutantStatus.Ignored },23 });24}25function mutantRunPlan(overrides?: Partial<MutantRunOptions & MutantTestCoverage>): MutantRunPlan {26 const mutant = factory.mutantTestCoverage(overrides);27 return factory.mutantRunPlan({28 runOptions: factory.mutantRunOptions({ ...overrides, activeMutant: mutant }),29 mutant,30 });31}32describe(MutationTestExecutor.name, () => {33 let reporterMock: Required<Reporter>;34 let testRunnerPoolMock: sinon.SinonStubbedInstance<I<Pool<TestRunner>>>;35 let checkerPoolMock: sinon.SinonStubbedInstance<I<Pool<I<CheckerFacade>>>>;36 let sut: MutationTestExecutor;37 let mutants: MutantTestCoverage[];38 let mutantTestPlans: MutantTestPlan[];39 let checker: sinon.SinonStubbedInstance<I<CheckerFacade>>;40 let mutationTestReportHelperMock: sinon.SinonStubbedInstance<MutationTestReportHelper>;41 let mutantTestPlannerMock: sinon.SinonStubbedInstance<MutantTestPlanner>;42 let timerMock: sinon.SinonStubbedInstance<Timer>;43 let testRunner: sinon.SinonStubbedInstance<Required<TestRunner>>;44 let concurrencyTokenProviderMock: sinon.SinonStubbedInstance<ConcurrencyTokenProvider>;45 let sandboxMock: sinon.SinonStubbedInstance<Sandbox>;46 beforeEach(() => {47 reporterMock = factory.reporter();48 mutationTestReportHelperMock = sinon.createStubInstance(MutationTestReportHelper);49 mutantTestPlannerMock = sinon.createStubInstance(MutantTestPlanner);50 timerMock = sinon.createStubInstance(Timer);51 testRunner = factory.testRunner();52 testRunnerPoolMock = createTestRunnerPoolMock();53 checkerPoolMock = createCheckerPoolMock();54 checker = { init: sinon.stub(), group: sinon.stub(), check: sinon.stub(), dispose: sinon.stub() };55 concurrencyTokenProviderMock = sinon.createStubInstance(ConcurrencyTokenProvider);56 sandboxMock = sinon.createStubInstance(Sandbox);57 (58 checkerPoolMock.schedule as sinon.SinonStub<59 [Observable<Mutant>, (checker: I<CheckerFacade>, arg: Mutant) => Promise<CheckResult>],60 Observable<CheckResult>61 >62 ).callsFake((item$, task) => item$.pipe(mergeMap((item) => task(checker, item))));63 (64 testRunnerPoolMock.schedule as sinon.SinonStub<65 [Observable<MutantTestCoverage>, (testRunner: TestRunner, arg: MutantTestCoverage) => Promise<MutantRunResult>],66 Observable<MutantRunResult>67 >68 ).callsFake((item$, task) => item$.pipe(mergeMap((item) => task(testRunner, item))));69 mutants = [factory.mutant()];70 mutantTestPlans = [];71 mutantTestPlannerMock.makePlan.resolves(mutantTestPlans);72 sut = testInjector.injector73 .provideValue(coreTokens.reporter, reporterMock)74 .provideValue(coreTokens.checkerPool, checkerPoolMock)75 .provideValue(coreTokens.testRunnerPool, testRunnerPoolMock)76 .provideValue(coreTokens.timeOverheadMS, 42)77 .provideValue(coreTokens.mutants, mutants)78 .provideValue(coreTokens.mutantTestPlanner, mutantTestPlannerMock)79 .provideValue(coreTokens.mutationTestReportHelper, mutationTestReportHelperMock)80 .provideValue(coreTokens.sandbox, sandboxMock)81 .provideValue(coreTokens.timer, timerMock)82 .provideValue(coreTokens.testRunnerPool, testRunnerPoolMock)83 .provideValue(coreTokens.concurrencyTokenProvider, concurrencyTokenProviderMock)84 .injectClass(MutationTestExecutor);85 });86 function arrangeMutationTestReportHelper() {87 mutationTestReportHelperMock.reportMutantStatus.returnsArg(0);88 mutationTestReportHelperMock.reportCheckFailed.returnsArg(0);89 mutationTestReportHelperMock.reportMutantRunResult.returnsArg(0);90 mutationTestReportHelperMock.reportAll.returnsArg(0);91 }92 function arrangeScenario(overrides?: { mutantRunPlan?: MutantRunPlan; checkResult?: CheckResult; mutantRunResult?: MutantRunResult }) {93 checker.check.resolves([[overrides?.mutantRunPlan ?? mutantRunPlan(), overrides?.checkResult ?? factory.checkResult()]]);94 testRunner.mutantRun.resolves(overrides?.mutantRunResult ?? factory.survivedMutantRunResult());95 arrangeMutationTestReportHelper();96 }97 describe('early result', () => {98 it('should short circuit ignored mutants (not check or run them)', async () => {99 // Arrange100 mutantTestPlans.push(ignoredEarlyResultPlan({ id: '1', statusReason: '1 is ignored' }));101 mutantTestPlans.push(ignoredEarlyResultPlan({ id: '2', statusReason: '2 is ignored' }));102 // Act103 const actualResults = await sut.execute();104 // Assert105 expect(testRunner.mutantRun).not.called;106 expect(checker.check).not.called;107 expect(actualResults).lengthOf(2);108 });109 it('should not run mutants that are uncovered by tests', async () => {110 // Arrange111 arrangeScenario();112 mutantTestPlans.push(mutantRunPlan({ id: '1', testFilter: [] }));113 // Act114 await sut.execute();115 // Assert116 expect(testRunner.mutantRun).not.called;117 });118 it('should report an ignored mutant as `Ignored`', async () => {119 // Arrange120 arrangeScenario();121 mutantTestPlans.push(ignoredEarlyResultPlan({ id: '1', statusReason: '1 is ignored' }));122 // Act123 await sut.execute();124 // Assert125 sinon.assert.calledWithExactly(mutationTestReportHelperMock.reportMutantStatus, mutantTestPlans[0].mutant, MutantStatus.Ignored);126 });127 it('should report an uncovered mutant with `NoCoverage`', async () => {128 // Arrange129 arrangeScenario();130 mutantTestPlans.push(mutantRunPlan({ id: '1', testFilter: [] }));131 // Act132 await sut.execute();133 // Assert134 expect(mutationTestReportHelperMock.reportMutantStatus).calledWithExactly(mutantTestPlans[0].mutant, MutantStatus.NoCoverage);135 });136 });137 describe('execute check', () => {138 beforeEach(() => {139 testInjector.options.checkers.push('foo');140 });141 it('should report non-passed check results as "checkFailed"', async () => {142 // Arrange143 const mutant = mutantRunPlan({ id: '1' });144 const failedCheckResult = factory.checkResult({ reason: 'Cannot find foo() of `undefined`', status: CheckStatus.CompileError });145 checker.group.resolves([[mutant]]);146 checker.check.resolves([[mutant, failedCheckResult]]);147 mutantTestPlans.push(mutant);148 // Act149 await sut.execute();150 // Assert151 expect(mutationTestReportHelperMock.reportCheckFailed).calledWithExactly(mutantTestPlans[0].mutant, failedCheckResult);152 });153 it('should group mutants buffered by time', async () => {154 // Arrange155 const clock = sinon.useFakeTimers();156 const plan = mutantRunPlan({ id: '1' });157 const plan2 = mutantRunPlan({ id: '2' });158 arrangeMutationTestReportHelper();159 testRunner.mutantRun.resolves(factory.survivedMutantRunResult());160 const secondCheckerTask = new Task<Array<[MutantRunPlan, CheckResult]>>();161 checker.check162 .withArgs(sinon.match.string, [plan])163 .resolves([[plan, factory.checkResult()]])164 .withArgs(sinon.match.string, [plan2])165 .returns(secondCheckerTask.promise)166 .withArgs(sinon.match.string, [plan, plan2])167 .resolves([168 [plan, factory.checkResult()],169 [plan2, factory.checkResult()],170 ]);171 // Add a second checker process172 testInjector.options.checkers.push('bar');173 mutantTestPlans.push(plan, plan2);174 checker.group175 .withArgs('foo', [plan, plan2])176 .resolves([[plan], [plan2]])177 .withArgs('bar', [plan])178 .resolves([[plan]])179 .withArgs('bar', [plan2])180 .resolves([[plan2]]);181 // Act182 const onGoingAct = sut.execute();183 // Assert184 await tick();185 // Assert that checker is called for the first 2 groups186 expect(checker.group).calledOnce;187 expect(checker.check).calledTwice;188 sinon.assert.calledWithExactly(checker.check, 'foo', [plan]);189 sinon.assert.calledWithExactly(checker.check, 'foo', [plan2]);190 // Assert first check resolved, now tick the clock 10s in the future191 clock.tick(10_001);192 await tick();193 // Now the second grouping should have happened194 expect(checker.group).calledTwice;195 expect(checker.check).calledThrice;196 sinon.assert.calledWithExactly(checker.check, 'bar', [plan]);197 // Now resolve the second checker task198 secondCheckerTask.resolve([[plan2, factory.checkResult()]]);199 await onGoingAct;200 // Finally all checks should have been done201 expect(checker.group).calledThrice;202 expect(checker.check).callCount(4);203 sinon.assert.calledWithExactly(checker.check, 'bar', [plan2]);204 });205 it('should short circuit failed checks', async () => {206 // Arrange207 testInjector.options.checkers.push('bar');208 const plan = mutantRunPlan({ id: '1' });209 const plan2 = mutantRunPlan({ id: '2' });210 arrangeMutationTestReportHelper();211 testRunner.mutantRun.resolves(factory.survivedMutantRunResult());212 checker.check213 .withArgs('foo', [plan])214 .resolves([[plan, factory.checkResult({ status: CheckStatus.CompileError })]])215 .withArgs('foo', [plan2])216 .resolves([[plan2, factory.checkResult({ status: CheckStatus.Passed })]])217 .withArgs('bar', [plan2])218 .resolves([[plan2, factory.checkResult({ status: CheckStatus.Passed })]]);219 mutantTestPlans.push(plan, plan2);220 checker.group221 .withArgs('foo', [plan, plan2])222 .resolves([[plan], [plan2]])223 .withArgs('bar', [plan2])224 .resolves([[plan2]]);225 // Act226 const mutantResults = await sut.execute();227 // Assert228 expect(checker.check).calledThrice;229 sinon.assert.neverCalledWith(checker.check, 'bar', [plan]);230 expect(mutantResults).deep.eq([plan.mutant, plan2.mutant]);231 });232 it('should check mutants in groups', async () => {233 // Arrange234 const plan1 = mutantRunPlan({ id: '1' });235 const plan2 = mutantRunPlan({ id: '2' });236 arrangeScenario();237 checker.group.resolves([[plan1], [plan2]]);238 mutantTestPlans.push(plan1);239 mutantTestPlans.push(plan2);240 // Act241 await sut.execute();242 // Assert243 expect(checker.check).calledTwice;244 sinon.assert.calledWithExactly(checker.check, 'foo', [plan1]);245 sinon.assert.calledWithExactly(checker.check, 'foo', [plan2]);246 });247 it('should report failed check mutants only once (#3461)', async () => {248 // Arrange249 const plan1 = mutantRunPlan({ id: '1' });250 const plan2 = mutantRunPlan({ id: '2' });251 const failedCheckResult = factory.failedCheckResult();252 arrangeScenario({ checkResult: failedCheckResult });253 checker.group.resolves([[plan1], [plan2]]);254 mutantTestPlans.push(plan1);255 mutantTestPlans.push(plan2);256 // Act257 await sut.execute();258 // Assert259 expect(mutationTestReportHelperMock.reportCheckFailed).calledTwice;260 sinon.assert.calledWithExactly(mutationTestReportHelperMock.reportCheckFailed, plan1.mutant, failedCheckResult);261 sinon.assert.calledWithExactly(mutationTestReportHelperMock.reportCheckFailed, plan1.mutant, failedCheckResult);262 });263 it('should free checker resources after checking stage is complete', async () => {264 // Arrange265 const plan = mutantRunPlan({ id: '1' });266 mutantTestPlans.push(plan);267 const checkTask = new Task<[[MutantRunPlan, CheckResult]]>();268 const testRunnerTask = new Task<MutantRunResult>();269 testRunner.mutantRun.returns(testRunnerTask.promise);270 checker.group.resolves([[plan]]);271 checker.check.returns(checkTask.promise);272 // Act & assert273 const executePromise = sut.execute();274 checkTask.resolve([[plan, factory.checkResult()]]);275 await tick(2);276 expect(checkerPoolMock.dispose).called;277 expect(concurrencyTokenProviderMock.freeCheckers).called;278 testRunnerTask.resolve(factory.killedMutantRunResult());279 await executePromise;280 });281 });282 describe('execute test', () => {283 it('should schedule mutants to be tested', async () => {284 // Arrange285 arrangeScenario();286 const plan1 = mutantRunPlan({ id: '1' });287 const plan2 = mutantRunPlan({ id: '2' });288 mutantTestPlans.push(plan1, plan2);289 // Act290 await sut.execute();291 // Assert292 expect(testRunnerPoolMock.schedule).calledOnce;293 expect(testRunner.mutantRun).calledWithExactly(plan1.runOptions);294 expect(testRunner.mutantRun).calledWithExactly(plan2.runOptions);295 });296 it('should sort the mutants that reload the environment last', async () => {297 // Arrange298 arrangeScenario();299 const plan1 = mutantRunPlan({ id: '1', reloadEnvironment: true });300 const plan2 = mutantRunPlan({ id: '2', reloadEnvironment: false });301 const plan3 = mutantRunPlan({ id: '3', reloadEnvironment: true });302 mutantTestPlans.push(plan1, plan2, plan3);303 // Act304 await sut.execute();305 // Assert306 sinon.assert.callOrder(307 testRunner.mutantRun.withArgs(plan2.runOptions),308 testRunner.mutantRun.withArgs(plan1.runOptions),309 testRunner.mutantRun.withArgs(plan3.runOptions)310 );311 });312 it('should report mutant run results', async () => {313 // Arrange314 const plan = mutantRunPlan({ static: true });315 const mutantRunResult = factory.killedMutantRunResult({ status: MutantRunStatus.Killed });316 mutantTestPlans.push(plan);317 arrangeScenario({ mutantRunResult });318 // Act319 await sut.execute();320 // Assert321 expect(mutationTestReportHelperMock.reportMutantRunResult).calledWithExactly(plan.mutant, mutantRunResult);322 });323 });324 it('should log a done message when it is done', async () => {325 // Arrange326 timerMock.humanReadableElapsed.returns('2 seconds, tops!');327 // Act328 await sut.execute();329 // Assert330 expect(testInjector.logger.info).calledWithExactly('Done in %s.', '2 seconds, tops!');331 });...
4-mutation-test-executor.ts
Source:4-mutation-test-executor.ts
...102 );103 const [passedCheckResult$, failedCheckResult$] = partition(checkTask$, ({ checkResult }) => checkResult.status === CheckStatus.Passed);104 const checkResult$ = failedCheckResult$.pipe(105 map((failedMutant) =>106 this.mutationTestReportHelper.reportCheckFailed(failedMutant.mutant, failedMutant.checkResult as Exclude<CheckResult, PassedCheckResult>)107 )108 );109 const passedMutant$ = passedCheckResult$.pipe(map(({ mutant }) => mutant));110 return { checkResult$, passedMutant$ };111 }112 private executeRunInTestRunner(input$: Observable<MutantTestCoverage>): Observable<MutantResult> {113 return this.testRunnerPool.schedule(input$, async (testRunner, mutant) => {114 const mutantRunOptions = this.createMutantRunOptions(mutant);115 const result = await testRunner.mutantRun(mutantRunOptions);116 return this.mutationTestReportHelper.reportMutantRunResult(mutant, result);117 });118 }119 private createMutantRunOptions(activeMutant: MutantTestCoverage): MutantRunOptions {120 const timeout = this.options.timeoutFactor * activeMutant.estimatedNetTime + this.options.timeoutMS + this.timeOverheadMS;...
Using AI Code Generation
1var reportCheckFailed = require('stryker-parent').reportCheckFailed;2reportCheckFailed('my message');3var reportCheckFailed = require('stryker-parent').reportCheckFailed;4reportCheckFailed('my message');5var reportCheckFailed = require('stryker-parent').reportCheckFailed;6reportCheckFailed('my message');7var reportCheckFailed = require('stryker-parent').reportCheckFailed;8reportCheckFailed('my message');9var reportCheckFailed = require('stryker-parent').reportCheckFailed;10reportCheckFailed('my message');11var reportCheckFailed = require('stryker-parent').reportCheckFailed;12reportCheckFailed('my message');13var reportCheckFailed = require('stryker-parent').reportCheckFailed;14reportCheckFailed('my message');15var reportCheckFailed = require('stryker-parent').reportCheckFailed;16reportCheckFailed('my message');17var reportCheckFailed = require('stryker-parent').reportCheckFailed;18reportCheckFailed('my message');19var reportCheckFailed = require('stryker-parent').reportCheckFailed;20reportCheckFailed('my message');21var reportCheckFailed = require('stryker-parent').reportCheckFailed;22reportCheckFailed('my message');23var reportCheckFailed = require('stryker-parent').reportCheckFailed;24reportCheckFailed('my message');
Using AI Code Generation
1const { reportCheckFailed } = require('stryker-parent');2reportCheckFailed();3const { reportCheckFailed } = require('stryker-parent');4reportCheckFailed();5const { reportCheckFailed } = require('stryker-parent');6reportCheckFailed();7const { reportCheckFailed } = require('stryker-parent');8reportCheckFailed();9const { reportCheckFailed } = require('stryker-parent');10reportCheckFailed();11const { reportCheckFailed } = require('stryker-parent');12reportCheckFailed();13const { reportCheckFailed } = require('stryker-parent');14reportCheckFailed();15const { reportCheckFailed } = require('stryker-parent');16reportCheckFailed();17const { reportCheckFailed } = require('stryker-parent');18reportCheckFailed();19const { reportCheckFailed } = require('stryker-parent');20reportCheckFailed();21const { reportCheckFailed } = require('stryker-parent');22reportCheckFailed();23const { reportCheckFailed } = require('stryker-parent');24reportCheckFailed();25const { reportCheckFailed } = require('stryker-parent');
Using AI Code Generation
1var reportCheckFailed = require('stryker-parent').reportCheckFailed;2reportCheckFailed('test failed');3var reportCheckFailed = require('stryker-parent').reportCheckFailed;4reportCheckFailed('test failed');5var reportCheckFailed = require('stryker-parent').reportCheckFailed;6reportCheckFailed('test failed');7var reportCheckFailed = require('stryker-parent').reportCheckFailed;8reportCheckFailed('test failed');9var reportCheckFailed = require('stryker-parent').reportCheckFailed;10reportCheckFailed('test failed');11var reportCheckFailed = require('stryker-parent').reportCheckFailed;12reportCheckFailed('test failed');13var reportCheckFailed = require('stryker-parent').reportCheckFailed;14reportCheckFailed('test failed');15var reportCheckFailed = require('stryker-parent').reportCheckFailed;16reportCheckFailed('test failed');17var reportCheckFailed = require('stryker-parent').reportCheckFailed;18reportCheckFailed('test failed');19var reportCheckFailed = require('stryker-parent').reportCheckFailed;20reportCheckFailed('test failed');21var reportCheckFailed = require('stryker-parent').reportCheckFailed;22reportCheckFailed('test failed');23var reportCheckFailed = require('stryker-parent').reportCheckFailed;24reportCheckFailed('test failed');
Using AI Code Generation
1var parent = require('stryker-parent');2parent.reportCheckFailed('test failed');3var parent = require('stryker-parent');4parent.reportCheckFailed('test failed');5var parent = require('stryker-parent');6parent.reportCheckFailed('test failed');7var parent = require('stryker-parent');8parent.reportCheckFailed('test failed');9var parent = require('stryker-parent');10parent.reportCheckFailed('test failed');11var parent = require('stryker-parent');12parent.reportCheckFailed('test failed');13var parent = require('stryker-parent');14parent.reportCheckFailed('test failed');15var parent = require('stryker-parent');16parent.reportCheckFailed('test failed');17var parent = require('stryker-parent');18parent.reportCheckFailed('test failed');19var parent = require('stryker-parent');20parent.reportCheckFailed('test failed');21var parent = require('stryker-parent');22parent.reportCheckFailed('test failed');23var parent = require('stryker-parent');24parent.reportCheckFailed('test failed');25var parent = require('stryker-parent');26parent.reportCheckFailed('test failed');27var parent = require('stryker-parent');28parent.reportCheckFailed('test failed');29var parent = require('stryker-parent');30parent.reportCheckFailed('test failed');
Using AI Code Generation
1var strykerParent = require('stryker-parent');2strykerParent.reportCheckFailed('some reason');3var strykerParent = require('stryker-parent');4strykerParent.reportCheckFailed('some reason');5var strykerParent = require('stryker-parent');6strykerParent.reportCheckFailed('some reason');7var strykerParent = require('stryker-parent');8strykerParent.reportCheckFailed('some reason');9var strykerParent = require('stryker-parent');10strykerParent.reportCheckFailed('some reason');11var strykerParent = require('stryker-parent');12strykerParent.reportCheckFailed('some reason');13var strykerParent = require('stryker-parent');14strykerParent.reportCheckFailed('some reason');15var strykerParent = require('stryker-parent');16strykerParent.reportCheckFailed('some reason');17var strykerParent = require('stryker-parent');18strykerParent.reportCheckFailed('some reason');19var strykerParent = require('stryker-parent');20strykerParent.reportCheckFailed('some reason');21var strykerParent = require('stryker-parent');22strykerParent.reportCheckFailed('some reason');23var strykerParent = require('stryker-parent');24strykerParent.reportCheckFailed('some reason');
Using AI Code Generation
1var strykerParent = require('stryker-parent');2var myCustomReporter = {3 onAllTestResults: function (results) {4 strykerParent.reportCheckFailed('My custom error message');5 }6};7module.exports = myCustomReporter;8module.exports = function (config) {9 config.set({10 });11};12module.exports = function (config) {13 config.set({14 });15};16module.exports = function (config) {17 config.set({18 });19};
Using AI Code Generation
1var reportCheckFailed = require('stryker-parent').reportCheckFailed;2describe('a failing test', function() {3 it('should fail', function() {4 reportCheckFailed('Expected 1 to equal 2');5 expect(1).to.equal(2);6 });7});8module.exports = function(config) {9 config.set({10 });11};12[2016-02-16 09:45:12.505] [INFO] SandboxPool - Creating 1 test runners (based on CPU count)13[2016-02-16 09:45:12.505] [INFO] MutatorFacade - 2 Mutant(s) generated14[2016-02-16 09:45:12.505] [INFO] SandboxPool - Creating 1 test runners (based on CPU count)
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!!