Module: Web::Testing

Defined in:
lib/web/testing.rb

Overview

Purpose

The testing module facilitates the testing of Web applications without the overhead of a web server to run.

Given these files:

script.rb
test.rb

where script.rb is:

#!/usr/bin/ruby
require 'web'

Web::process { 
  Web.write "param is #{Web["param"]}"
}

and test.rb is:

require 'web'
require 'test/unit'

class MyAppTest < Test::Unit::TestCase
    include Web::Testing

    def test_prints_content
        do_request "script.rb", "param" => "THIS!"
        assert_content "param is THIS!"
    end
end

Do this to run tests:

ruby test.rb

If you have a more complicated app, where the tests live in a different place than your scripts, you can use:

Web::set_docroot( path )

To tell narf where to find your cgi scripts.

Testing with Templates

Using Narflates you can test functionality without having to do lengthly string comparisons. For example, create the following file in ‘mytemplate.html’

<html>
  <body>
    {$myvar}
  </body>
</html>

Create a ‘script.rb’ as follows:

#!/usr/bin/narf
require 'web'

Web::process{
  Web.print_template "mytemplate.html", { "myvar" => "Hello World" }
}

Now, we can check that the right values got displayed without needing to check that the template is correct as a side effect. Save this into ‘test.rb’ and run it:

require 'web'

class MyAppTest < Test::Unit::TestCase
    include Web::Testing          # adds the modules

    def test_prints_content
        do_request "script.rb"
        assert_vars_includes "myvar" => "Hello World"

end

end

Testing Forms

The following example demonstrates testing a simple HTML form. Creating mytemplate.html as:

<html>
  <body>
    <form name="myform">
      <input type="text" name="foo">
      <input type="submit" name="submit" value="Submit">
  </body>
</html>

To print this form and handle a submit save this as ‘script.rb’:

#!/usr/bin/narf

require 'web'

Web::process {
  if Web["submit"]   # check to see whether a form was
      Web.puts "Form Submitted with value '#{Web["foo"]}'"  
  else
      Web.print_template "mytemplate.html"
  end
}

Use this ‘test.rb’ to test it:

class MyAppTest < Test::Unit::TestCase
    include Web::Testing          # adds the modules

    def test_prints_content

do_request “script.rb”

do_submit "myform", "foo" => "bar"
assert_content "Form Submitted with value '#{Web["foo"]}'"

end

end

Test <input type=“text|password|hidden”> and <textarea>

html:

<form name='aForm'>
<input name="bare">
<input name="named"   type="text"     value="foo">
<input name="pass"    type="password" value="secret">
<input name="obscure" type="hidden"   value="discrete">
<textarea name="big_text">
big paragraph here
</textarea>
</form>

assert:

assert_form_includes( 'aForm', "bare"     => "",
                               "named"    => "foo",
                               "pass"     => "secret",
                               "obscure"  => "discrete",
                               "big_text" => "big paragraph here" )

submit:

do_submit( 'aForm', "bare"     => "empty",
                    "named"    => "bare",
                    "pass"     => "shhhhh",
                    "obscure"  => "secretive",
                    "big_text" => "windbag" )

Test <input type=“file”>

html:

<form name='aForm' enctype='multipart/form-data'>
<input name="upload" type="file">
</form>

assert:

assert_form_includes( 'aForm', "upload" => "" )

submit:

do_submit( 'aForm', "upload" => Web::Upload.new(
                                  File.new( "testfile" ),
                                  "content-type",
                                  "original-filename" ) )

Test <select> and <input type=“radio”>

Test <select multiple> and <input type=“checkbox”>

Bugs: Unsupported behaviour

The following situations will have unknown results:

* Combining different types of elements into one field;
  i.e. <input name="field" type="text"> and <select name="field">
* Comparing <input name="page.name"> and <input name="page.content">
  with assert_vars_include("page" => { "name" => ..., "content" => ... } )

Defined Under Namespace

Classes: FieldNotFoundException, FormNotFoundException, MultiHashTree, MustSetDocrootForAbsolutePathException, SelectHash

Constant Summary collapse

@@test_session =
nil

Instance Method Summary collapse

Instance Method Details

#assert_content(expected, msg = "") ⇒ Object

Assert that the entire content displayed is equal to expected



345
346
347
# File 'lib/web/testing.rb', line 345

def assert_content expected, msg=""
  Web.assert_content expected, msg
end

Assert that the cookie key, has the cookie value



355
356
357
# File 'lib/web/testing.rb', line 355

def assert_cookie key, value, msg=""
  Web.assert_cookie key, value, msg
end

#assert_form_includes(formname, expected) ⇒ Object

Assert that the form displayed contains particular values



340
341
342
# File 'lib/web/testing.rb', line 340

def assert_form_includes formname, expected
  Web.assert_form_includes formname, expected
end

#assert_header(key, value, msg = "") ⇒ Object

Assert that the header key has the value ‘value’



350
351
352
# File 'lib/web/testing.rb', line 350

def assert_header key, value, msg=""
  Web.assert_header key, value, msg
end

#assert_options(formname, expected = {}) ⇒ Object

Assert that a form field has exactly the given options can’t assert order, though



361
362
363
364
365
366
# File 'lib/web/testing.rb', line 361

def assert_options( formname, expected={})
  options = Web.get_formreader.get_options(formname)
  expected.each{ |k,v|
    assert_equal( v.sort, options[k].sort )
  }
end

#assert_template_not_used(filename, msg = "") ⇒ Object

Assert that a give template was not displayed



330
331
332
# File 'lib/web/testing.rb', line 330

def assert_template_not_used filename, msg=""
  Web.assert_template_not_used filename, msg
end

#assert_template_used(filename, msg = "") ⇒ Object

Assert that a give template was displayed



325
326
327
# File 'lib/web/testing.rb', line 325

def assert_template_used filename, msg=""
  Web.assert_template_used filename, msg
end

#assert_vars_includes(expected) ⇒ Object

Assert that the values passed in to expected were set on the template



335
336
337
# File 'lib/web/testing.rb', line 335

def assert_vars_includes expected
  Web.assert_vars_includes expected
end

#do_request(webpath, parameters = {}) ⇒ Object

Run a request, parameters are the name value pairs that would be passed in the query string. The webpath is a document root relative path to a ruby script.



241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'lib/web/testing.rb', line 241

def do_request(webpath, parameters={}) 
  options = {}
  @@test_session ||= {}
  options[:session] = @@test_session
  options[:params] = parameters
  options[:document_root] = Web.get_docroot
  options[:out] = StringIO.new
  script_path, script_name, path_info = get_script_part(webpath)
  
  options[:path_info] = path_info
  options[:script_name] = script_name
  load_request( options, script_path, webpath )
end

#do_submit(formname, newvalues = {}) ⇒ Object

Submit the form ‘formname’ with the formfields described in newvalues



278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
# File 'lib/web/testing.rb', line 278

def do_submit( formname, newvalues={} )
  form = Web.get_form(formname)
  
  if form == nil
    #if Web.get_form_fields[formname] == nil
	raise FormNotFoundException.new("Form '#{formname}' does not exist") 
  end
  
  #MultiHashTree::flatten(newvalues).keys.each do |key|
	#unless( Web.get_form_fields[formname].valid_key?(key) )
	 # raise FieldNotFoundException.new( "#{ key } is not present in form" )
	#end
  #end

  webpath = nil
  
  #Web.get_html_tree.get_elements("form").each { |form|
  #  if (form.attribute("name") == formname)
  #    webpath = form.attribute("action")
  #  end
  #}
  webpath = form.action

  unless (webpath)
    webpath = Web.options[:webpath]
  end

  script_path, script_name, path_info = get_script_part(webpath)

  oldRequest = Web.get_cgi

  options = {}
  @@test_session ||= {}
  options[:session] = @@test_session
  options[:out] = StringIO.new
  ### patrick
  options[:params] = form.merge_fields( newvalues )
  #options[:params] = Web.get_form_fields[formname].params(MultiHashTree::flatten(newvalues))
  options[:document_root] = oldRequest.document_root

  options[:path_info] = path_info     #oldRequest.path_info
  options[:script_name] = script_name #oldRequest.script_name

  load_request( options, script_path, webpath )
end

#get_script_part(webpath) ⇒ Object

:nodoc:



372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
# File 'lib/web/testing.rb', line 372

def get_script_part(webpath)  #:nodoc:
  # two cases:
  #   absolute webpath (requires Web.get_docroot to be correct)
  #   relative webpath (doesn't require Web.get_docroot to be correct)
  if ( webpath =~ /^\// )
    prefix = Web.get_docroot
    raise MustSetDocrootForAbsolutePathException unless prefix
    path = "/"
  else
    prefix = ""
    path = ""
  end

  new_script_path = ""
  webpath.split("/").each do |file|
	file =~ /^([a-zA-Z]{1,1}:)$/

    if (path.empty?)
      newpath = file
    else
      newpath = File.join( path , file ).gsub("//","/") 
    end

    new_script_path = ""
    if (prefix.empty?)
      new_script_path = newpath
    else
      new_script_path = File.join( prefix, newpath ).gsub("//","/") 
    end
    
    if (File.file?(new_script_path))
	  return new_script_path, "/" + File.basename( new_script_path ), webpath[newpath.length...webpath.length]
	end 
	
	path = newpath
  end

  if (!File.exists?(new_script_path) && prefix.empty?)
    return get_script_part( "/" + webpath )
  end

  return new_script_path, "/" + File.basename( new_script_path ), ""
end

#load_request(options, script_path, webpath) ⇒ Object

:nodoc:



255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/web/testing.rb', line 255

def load_request( options, script_path, webpath ) #:nodoc:
  options[:webpath] = webpath

  # out with the old....
  #Web::get_cgi.close
  Web::set_cgi nil
  error = nil
  Web::load( script_path, options )
  
  if Web.status == "302"
   Web.location =~ /(.*)\?(.*)/
    target = $1
    params = Parser.parse_query_string($2)
    
    unless (target =~ /^\//)
      webpath =~ /(.*)#{File.basename(script_path)}/
      target = $1 + target
   end
    do_request( target, params )
  end
end

#remove_trailing_slashes(filename) ⇒ Object

:nodoc:



368
369
370
# File 'lib/web/testing.rb', line 368

def remove_trailing_slashes(filename)  #:nodoc:
  /(.*?)\/?$/.match(filename)[1]
end

#reset_sessionObject

Reset the session used by the test framework. Call prior to all tests that rely on the session being clean



234
235
236
# File 'lib/web/testing.rb', line 234

def reset_session
  @@test_session = nil
end

#select(*args) ⇒ Object



216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/web/testing.rb', line 216

def select( *args )
  hash = {}
  
  if (args.length == 1 and args[0].kind_of? Hash)
    hash = args[0]
  else
    args.each { |e|
      hash[e] = true
    }
  end
  
  hash
end

#set_docroot(path) ⇒ Object

When testing, this is a useful method to tell NARF where to find your scripts



212
213
214
# File 'lib/web/testing.rb', line 212

def set_docroot( path )
  Web::set_docroot( path )
end