How to structure a clj-webdriver project?

56 views
Skip to first unread message

Dan

unread,
Jul 5, 2015, 10:01:14 AM7/5/15
to clj-we...@googlegroups.com
I want to use clj-webdriver to test a decently sized (non-clojure) web application. However, I'm having difficulty understanding how to structure the project (or any clj-webdriver project that is too big for a single namespace of functions). If it matters, the nature of the application will require some of my tests to have two separate browser instances interact with each other.

I have used the common page object pattern using webdriver with Python to create an interaction API separate from tests. With it I did the following:

- Each view was its own class with a reference to the webdriver instance
- Any useful elements were attached to the class with a local symbol so the locator was only in one place, e.g.:

username_field = Element('input .username')

- Methods of the Page Object either retrieved information or interacted with the page
- Actions which triggered a new view returned a different page object.
- Each page object had a list of functions called "conditions" used to validate the correct view was active. This is also used to determine which view is active when an action may trigger one of several different views. These were automatically called when a different page object was returned, and an exception thrown if none of the page objects given passed validation within the polling time.

I'm having trouble working out how to structure anything of a non-trivial size in clojure. I have not even seen an example of clj-webdriver where the element locators are abstracted. The very basics of using clojure instead of python for this are easy for me to grasp, for example defining functions like below:

(defn fill-login [driver username password]
 
(-> driver
   
(input-text "input .username" username)
   
(input-text "input .password" password)
   
(click "button .submit")))

The difficult part is understanding things like:

- Where do I store reference to element locators? In a map? In vars in a namespace? Do I make a single "database" of elements or do I segregate them by views/components they belong to?
- How do I group/organize functions? Do I just replace defining a class with defining a new namespace?
- How do I define page validation? How/when do I call it? (In the interaction API or in the tests).
- How do I facilitate "discoverability" when using the interaction API from the REPL? With a page object, my current instance has reference to all the elements, queries, and actions available to me on this view just by hitting dot-tab.
- Is it possible to define which pages (and how they) link together? Is it even necessary? What, if any, application state do I model on my end?
- How do I handle components (e.g. a menu) that exist on multiple pages?
- How do I access the interaction API from tests? If I'm using all namespaces, do I then have to require each namespace?
- Should I be tracking any kind of context on my end? Does it go in the interaction API or the tests?

I would really appreciate some guidance or examples.
Reply all
Reply to author
Forward
0 new messages