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::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



465
466
467
# File 'lib/web/testing.rb', line 465

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

Assert that the cookie key, has the cookie value



475
476
477
# File 'lib/web/testing.rb', line 475

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



460
461
462
# File 'lib/web/testing.rb', line 460

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’



470
471
472
# File 'lib/web/testing.rb', line 470

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



481
482
483
484
485
486
# File 'lib/web/testing.rb', line 481

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



450
451
452
# File 'lib/web/testing.rb', line 450

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



445
446
447
# File 'lib/web/testing.rb', line 445

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



455
456
457
# File 'lib/web/testing.rb', line 455

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.



353
354
355
356
357
358
359
360
361
362
363
364
365
366
# File 'lib/web/testing.rb', line 353

def do_request(webpath, parameters={}) 
  options = {}
  @@test_session ||= {}
  options[:session] = @@test_session
  options[:env] = parameters[:env]
  options[:request] = parameters
  options[:document_root] = Web::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



398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'lib/web/testing.rb', line 398

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)

  old_connection = Web.connection

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

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

  load_request( options, script_path, webpath )
end

#get_script_part(webpath) ⇒ Object

:nodoc:



492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
# File 'lib/web/testing.rb', line 492

def get_script_part(webpath)  #:nodoc:
  # two cases:
  #   absolute webpath (requires Web::docroot to be correct)
  #   relative webpath (doesn't require Web::docroot to be correct)
  if ( webpath =~ /^\// )
    prefix = Web::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:



368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/web/testing.rb', line 368

def load_request( options, script_path, webpath ) #:nodoc:
  options[:webpath] = webpath
  ### re-throw errors
  Web::config[:error_style] = :custom
  Web::config[:error_handler] = lambda do |error|
    raise error
  end
  
  # out with the old....
  #Web::connection.close
  Web::connection = nil
  error = nil
  Web::open( options ) do
    Web::load( script_path )
  end
  
  if Web.status == "302"
   Web.location =~ /(.*)\?(.*)/
    target = $1
    params = Connection::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:



488
489
490
# File 'lib/web/testing.rb', line 488

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



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

def reset_session
  @@test_session = nil
end

#select(*args) ⇒ Object



328
329
330
331
332
333
334
335
336
337
338
339
340
# File 'lib/web/testing.rb', line 328

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

#write_file(path, content) ⇒ Object



315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/web/testing.rb', line 315

def write_file( path, content )
  filename = File.join( Web::docroot, path )
  filedir  = File.dirname(filename)
  unless File.exists? filedir
    require 'fileutils'
    FileUtils::mkdir_p(filedir, :verbose => false)
  end
  
  File.open( filename, "w" ) do |f|
    f.write content
  end
end