Skip to content
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
Cannot retrieve contributors at this time

CL Selenium WebDriver

CL Selenium WebDriver is a binding library to the Selenium 2.0


This software is in development. The APIs will be likely to change.


;; see examples/*.lisp and t/*.lisp
(in-package :cl-user)

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload :cl-selenium))

(defpackage go-test
  (:use :cl :cl-selenium))

(in-package :go-test)

(defparameter *code* "
package main
import \"fmt\"

func main() {
    fmt.Print(\"Hello WebDriver!\")

(with-session ()
  (setf (url) "")
  (let ((elem (find-element "#code" :by :css-selector)))
    (element-clear elem)
    (element-send-keys elem *code*))
  (let ((btn (find-element "#run")))
    (element-click btn))

     with div = (find-element "#output")
     for ouput = (element-text div)
     while (equal ouput "Waiting for remote server...")
     do (sleep 0.1)
     finally (print ouput)))


git clone ~/quicklisp/local-projects/
(ql:quickload :cl-selenium)

You need a running instance of selenium-server-standalone.

Download it and run:

curl -L0 -o selenium-server-standalone.jar
java -jar selenium-server-standalone.jar


There is a :cl-selenium-utils package which should reduce boilerplate. For example:

(defpackage my-test
  (:use :cl :cl-selenium)
  (:import-from :cl-selenium-utils

(in-package :my-test)

(with-session ()
  (setf (url) "")
  (send-keys "cl-selenium-webdriver")
  (click "[name=btnK]")
  (wait-for "#resultStats"))

Interactive session

You can just start the session and control it from your repl:

(in-package :my-test)


(setf (url) "")
(send-keys "cl-selenium-webdriver")
(send-keys (key :enter))
(classlist "#slim_appbar") ; prints ("ab_tnav_wrp")


Utils API conventions

If utility function needs an element to work on it defaults to (active-element).

(click) ; click on the current active element.

You can also pass a css selector as a last parameter.

(print (id "#submit")) ; print id the of matched element

(assert (= (first (classlist "div")) "first-div-ever"))

To change default element you can:

(setf cl-selenium-utils:*default-element-func* (lambda () (find-element "input[type=submit]"))

Waiting for the reaction

Often you need to wait for some action to be done. For example if you do a (click) on the button to load search results, you need to wait them to load.

(wait-for ".search-result" :timeout 10) ; wait 10 seconds

Timeout defaults to 30 seconds. You can globally change it:

(setf cl-selenium-utils:*timeout* 3)

Running tests


(ql:quickload '(:cl-selenium :prove))
(setf prove:*enable-colors* nil)
(prove:run :cl-selenium-test)




Licensed under the MIT License.