1

I have a selenium UI test written with F# (using canopy selenium nuget package). I have a module that defines page selectors and helper functions. The page module is called by a test module. Within the test module, I am calling a function called 'handlemobimodals()', which runs four sub functions (if/else code blocks) that look for the existence of an element on a page and click on it, if it exists.

The problem I'm facing is that when the 'handlemobimodals()' function is called for a second time within the test, I get a Stack Overflow Exception (WebDriver Process is terminated due to StackOverflowException), right after its first sub function is called.

The function runs completely fine for the first time (called indirectly from another function earlier in the test), but fails the second time when called directly in the test. I'm pretty new to F# and I can't figure out how I'm causing a recursion in my test as the stackoverflow exception suggests.

Any insights would be greatly appreciated.

Snippet from Page Module:

module some_page

    let isOKGotItDisplayed () =
      isDisplayed <| "div.action-button.dismiss-overlay"

    let clickOKGotit() = 
      if isOKGotItDisplayed() = true then
        click "OK, GOT IT"
        describe "OK, Got It clicked"
      else describe "Got nothing"

    let isGoToSearchDisplayed() =
      isDisplayed <| "button:contains('Go to Search')"

    let clickGoToSearch() = 
      if isGoToSearchDisplayed() = true then
        click "button:contains('Go to Search')"
        describe "go search button clicked"
      else describe "Got nothing"

    let isSkipDisplayed() =
      isDisplayed <| "#uploadPhotos > div.continue.skip"

    let clickSkip() = 
      if isSkipDisplayed() = true then
        click "Skip"
        describe "Skip link clicked"
      else describe "Got nothing"

    let mobiOkayGotItDisplayed () =
      isDisplayed <| "Okay, got it"

    let mobiOKGotit() =
      if mobiOkayGotItDisplayed() = true then
        click "Okay, got it"
        describe "Okay, got it"
      else describe "Got nothing"

    let handleMobiModals() = 
      clickSkip()
      clickOKGotit()
      clickGoToSearch()
      mobiOKGotit()


    loginForPathAs user =
       username << "somename"
       paswword << "somepassword"
       handleMobiModals()

Snippet from Test Module (note the first instance of the handleMobiModals function is called in the LoginforPathAs function, which is defined in the same page definition module):

module_sometest

open some_page

      "Test 001: Log in and do something" &&& fun _ ->
         newBrowser platform
         loginForPathAs user1     
         displayed  quicknoteSendButton
         click quicknoteSendButton
         handleMobiModals ()
         displayed "Subscribe"

Note: Snippets are edited for simplicity and clarity.

codet3str
  • 93
  • 1
  • 5
  • Quick comment: there's no need for `= true` when you're checking the result of Boolean functions. Just use `if mobiOkayGotItDisplayed()` rather than `if mobiOkayGotItDisplayed() = true`. – rmunn Apr 09 '17 at 09:02
  • @munn, since there no need for `= true` from language point of view, some teams/developers prefer explicitly write expected condition, because in case when you omit `= true`, readability of your code will depend on how descriptive condition function named. – Fabio Apr 09 '17 at 09:36
  • @rmunn the result of the functions evaluated with 'if' (e.g. **mobiOkayGotItDisplayed()** ) could be true or false. – codet3str Apr 09 '17 at 17:45
  • 2
    @codet3str - Precisely. When you have a Boolean function (that is, a function that could return true or false), there's no need for `if function() = true`, because the `if` statement **already** checks if something is true. So saying `if function()` is *exactly equivalent* to saying `if function() = true`. And `if isSkipDisplayed() then (code)` reads much better than `if isSkipDisplayed() = true then (code)`. Style matters: when you write code that's easier to read and understand, you end up producing fewer bugs. – rmunn Apr 10 '17 at 00:05
  • @Fabio - If your function names don't easily communicate what they do, *you have chosen bad names* for your functions, and you'll have a lot more problems than can be solved by simply adding `= true` to your `if` statements. And if you have *good* function names, then the `= true` becomes redundant and makes your code a tiny bit harder to read. That unnecessary `= true` after each `if` makes more work for the guy writing the code, *and* more work for the guy reading the code, and it's all unnecessary. Teams that specify that in their coding style have chosen a *bad coding style*. – rmunn Apr 10 '17 at 00:09
  • @Fabio - That said, if your team has already specified something in their coding style guidelines, *you should follow those guidelines **even if you don't like them***. So if I was on a team like you describe, that has chosen to add an unnecessary `= true` to every `if` statement, I would: 1) try to persuade the team lead that that's a bad idea, and 2) add that unnecessary `= true` to the `if` statements as long as that's what the code style guidelines say. – rmunn Apr 10 '17 at 00:11
  • 1
    @rmunn, thanks for the insight - makes sense. I applied your suggestion on using the cleaner way to use the boolean functions. However, I'm still getting the stack overflow exception described earlier. – codet3str Apr 10 '17 at 04:08

2 Answers2

1

It's not a direct answer, but I believe it would help to find the problem much easier. I did notice something that makes it somewhat difficult to debug this problem. You're calling multiple functions from another function, and calling this single function from a test. Splitting out these functions into separate tests and changing the tests into WIP mode should help to pinpoint your issue. There are a lot of possible points of failure within that one test.

For instance, you can use before(fun _ -> some function(s) here) or once(fun _ -> some function(s) here) within your context in Canopy to start a new browser and login, separating that part from the test.

Michael Bowman
  • 245
  • 2
  • 12
  • Thanks for the suggestion. I just re-visited the issue and it appears to have resolved itself. I believe the most recent auto-update to Chrome fixed the problem - I definitely debug'd the code as much as I could, so I know there wasn't any issue with the logical flow (i.e. there was no re-cursive logic). – codet3str Jun 26 '17 at 22:10
0

This issue appears to have resolved itself. I believe my most recent auto-update for Chrome fixed the problem.

codet3str
  • 93
  • 1
  • 5