Speedup and simplify tests

This drastically speeds up tests and simplifies test writing by making
it so that no explicit calls for waiting are needed. Elements that are
queried for now implicitly waits for them to be available.

On my machine, tests used to take 3-4 minutes to complete. Now they take
~1 minute to complete.
This commit is contained in:
Joey Yakimowich-Payne 2020-02-16 19:19:21 -07:00 • committed by Andreas Rumpf
commit 5a4f44b4ee
7 changed files with 40 additions and 83 deletions

View file

@ -2,6 +2,9 @@ import os, options, unittest, strutils
import webdriver
import macros
const actionDelayMs {.intdefine.} = 0
## Inserts a delay in milliseconds between automated actions. Useful for debugging tests
macro with*(obj: typed, code: untyped): untyped =
## Execute a set of statements with an object
expectKind code, nnkStmtList
@ -12,24 +15,28 @@ macro with*(obj: typed, code: untyped): untyped =
if result[i].kind in {nnkCommand, nnkCall}:
result[i].insert(1, obj)
proc elementIsSome(element: Option[Element]): bool =
return element.isSome
proc elementIsNone(element: Option[Element]): bool =
return element.isNone
proc waitForElement*(session: Session, selector: string, strategy=CssSelector, timeout=20000, pollTime=50, waitCondition=elementIsSome): Option[Element]
template click*(session: Session, element: string, strategy=CssSelector) =
let el = session.findElement(element, strategy)
check el.isSome()
let el = session.waitForElement(element, strategy)
el.get().click()
template sendKeys*(session: Session, element, keys: string) =
let el = session.findElement(element)
check el.isSome()
let el = session.waitForElement(element)
el.get().sendKeys(keys)
template clear*(session: Session, element: string) =
let el = session.findElement(element)
check el.isSome()
let el = session.waitForElement(element)
el.get().clear()
template sendKeys*(session: Session, element: string, keys: varargs[Key]) =
let el = session.findElement(element)
check el.isSome()
let el = session.waitForElement(element)
# focus
el.get().click()
@ -37,47 +44,47 @@ template sendKeys*(session: Session, element: string, keys: varargs[Key]) =
session.press(key)
template ensureExists*(session: Session, element: string, strategy=CssSelector) =
let el = session.findElement(element, strategy)
check el.isSome()
discard session.waitForElement(element, strategy)
template check*(session: Session, element: string, function: untyped) =
let el = session.findElement(element)
let el = session.waitForElement(element)
check function(el)
template check*(session: Session, element: string,
strategy: LocationStrategy, function: untyped) =
let el = session.findElement(element, strategy)
let el = session.waitForElement(element, strategy)
check function(el)
template checkIsNone*(session: Session, element: string, strategy=CssSelector) =
let el = session.findElement(element, strategy)
check el.isNone()
discard session.waitForElement(element, strategy, waitCondition=elementIsNone)
template checkText*(session: Session, element, expectedValue: string) =
let el = session.findElement(element)
check el.isSome()
let el = session.waitForElement(element)
check el.get().getText() == expectedValue
proc waitForLoad*(session: Session, timeout=20000) =
proc waitForElement*(
session: Session, selector: string, strategy=CssSelector,
timeout=20000, pollTime=50,
waitCondition=elementIsSome
): Option[Element] =
var waitTime = 0
sleep(2000)
when actionDelayMs > 0:
sleep(actionDelayMs)
while true:
let loading = session.findElement(".loading")
if loading.isNone: return
sleep(1000)
waitTime += 1000
let loading = session.findElement(selector, strategy)
if waitCondition(loading):
return loading
sleep(pollTime)
waitTime += pollTime
if waitTime > timeout:
doAssert false, "Wait for load time exceeded"
proc wait*(session: Session, msTimeout: int = 5000) =
session.waitForLoad(msTimeout)
proc setUserRank*(session: Session, baseUrl, user, rank: string) =
with session:
navigate(baseUrl & "profile/" & user)
wait()
click "#settings-tab"
@ -85,13 +92,11 @@ proc setUserRank*(session: Session, baseUrl, user, rank: string) =
click("#rank-field option#rank-" & rank.toLowerAscii)
click "#save-btn"
wait()
proc logout*(session: Session) =
with session:
click "#profile-btn"
click "#profile-btn #logout-btn"
wait()
# Verify we have logged out by looking for the log in button.
ensureExists "#login-btn"
@ -108,8 +113,6 @@ proc login*(session: Session, user, password: string) =
sendKeys "#login-form input[name='password']", Key.Enter
wait()
# Verify that the user menu has been initialised properly.
click "#profile-btn"
checkText "#profile-btn #profile-name", user
@ -128,7 +131,6 @@ proc register*(session: Session, user, password: string, verify = true) =
sendKeys "#signup-form input[name='password']", password
click "#signup-modal .create-account-btn"
wait()
if verify:
with session:
@ -141,13 +143,11 @@ proc register*(session: Session, user, password: string, verify = true) =
proc createThread*(session: Session, title, content: string) =
with session:
click "#new-thread-btn"
wait()
sendKeys "#thread-title", title
sendKeys "#reply-textarea", content
click "#create-thread-btn"
wait()
checkText "#thread-title .title-text", title
checkText ".original-post div.post-content", content