Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
232 views
in Technique[技术] by (71.8m points)

javascript - Is there a way to run particular Protractor test depending on the result of the other test?

This kind of question has been asked before but most of this question has pretty complicated background. The scenario is simple. Let's say we are testing our favorite TODO app. Test cases are next: TC00 - 'User should be able to add a TODO item to the TODO list' TC01 - 'User should be able to rename TODO item' TC02 - 'User should be able to remove TODO item' I don't want to run the TC01 and TC02 if TC00 fails (the TODO item is not added so I have nothing to remove or rename)

So I've been researching on this question for the past 3 days and the most common answers fro this question are: ? Your tests should not depend on each other ? Protractor/Jasmine does not have feature to dynamically turn on/off tests ('it' blocks) There reason why I'm asking this question here is because it looks like a very widespread case and still no clear suggestion to handle this (I mean I could not find any) My javascript skills are poor but I understand that I need to play around, let's say' passing 'done' or adding the if with the test inside...

it('should add a todo' ()=> {
  todoInput.sendKeys('test')
  addButton.click();
  let item = element(by.cssContainingText('.list-item','test')
  expect(item.isPresent()).toBe(true)
}

In my case there are like 15 tests ('it' blocks) after adding the item to the list. And I want to skip SOME OF THE tests if the 'parent' test failed. PLEASE NOTE: There is a solution out there which allows to skip ALL remaining test if one fails. This does not suit my needs

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Man, I spent good couple of weeks researching this, and yes there was NO clear answers, until I realized how protractor works in details. If you understand this too you'll figure out the best option for you.

SOLUTION IS BELOW AFTER SHORT THEORY

1) If you try to pass async function to describe you see it'll fail, because it only accepts synchronous function

What it means for you, is that whatever condition you want to pass to it block, it can't be Promise based (Promise == resolves somewhen, but not immediately). What you're trying to do essentially IS a Promise (open page, do something and wait to see if the condition satisfies your criteria)

if (conditionIsTrue) { // can't be Promise
  it('name', () => {
  })
}

Thats first thing to consider...

2) When you run protractor, it picks up spec files specified in config and builds the queue of describe/it AND beforeAll/afterAll blocks. IMPORTANT DETAIL HERE IS THAT IT HAPPENS BEFORE THE BROWSER EVEN STARTED.

Look at this example

let conditionIsTrue; // undefined
  it('name', () => {
    conditionIsTrue = true;
  })
if (conditionIsTrue) { // still undefined
  it('name', () => {
  })
}

By the time Protractor reaches if() statement, the value of conditionIsTrue is still undefined. And it maybe overwritten inside of it block, when browser starts, later on, but not when it builds the queue. So it skips it.

In other words, protractor knows which describe blocks it'll run before it even opens the browser, and this queue can NOT be modified during execution

POSSIBLE SOLUTION

1.1 Define a global variable outside of describe

let conditionIsTrue; // undefined
describe("describe", () => {
  it('name1', async () => {
    conditionIsTrue = await element.isPresent(); // NOW IT'S TRUE if element is present
  })

  it('name2', async () => {
    if (conditionIsTrue) {
      //do whatever you want if the element is present
    } else {
      console.log("Skipping 'name2' test")
    }
  })
})

So you won't skip the it block itself, however you can skip anything inside of it

1.2 The same approach can be used for skipping it blocks across different specs, using environment variable. Example:

spec_1.js

describe(`Suite: 1`, () => {
  it("element is present", async () => {
    if (await element.isPresent()) {
      process.env.FLAG = true
    } else {
      process.env.FLAG = false
    }
  });
});

spec_2.js

describe(`Suite: 2`, () => {
  it("element is present", async () => {
    if (process.env.FLAG) {
      // do element specific actions
    }
  });
});
  1. Another possibility I found out, but never had a chance to check is to use Grunt task runner, which may help you implement the following scenario

    • Run protractor to execute one spec
    • Check a desired condition
    • Export this condition to environment variable
    • Exit protractor
    • In your Grunt task implement a conditional logic for executing the rests of conditional specs, by starting protractor again

But honestly, I don't see why you'd want to go this time consuming route, which requires a lot of code... But just as an FYI


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.9k users

...