[LON-CAPA-cvs] cvs: modules /goltermann/Tests Makefile Util.pm config.cfg runTests.pl /goltermann/Tests/template Template.pm /goltermann/internalTest/t InterfaceTest.pm ProblemTest.pm

goltermann goltermann at source.lon-capa.org
Tue Jun 18 05:47:27 EDT 2013


goltermann		Tue Jun 18 09:47:27 2013 EDT

  Added files:                 
    /modules/goltermann/Tests	Makefile Util.pm config.cfg runTests.pl 
    /modules/goltermann/internalTest/t	InterfaceTest.pm ProblemTest.pm 
    /modules/goltermann/Tests/template	Template.pm 
  Log:
  stable version, more compact
  
  
  
-------------- next part --------------

Index: modules/goltermann/Tests/Util.pm
+++ modules/goltermann/Tests/Util.pm
#!perl
use strict;
use warnings;

package Util;
use Test::More;
use Test::WWW::Selenium;
use Smart::Comments;

my $maxTimeout = 30000;
my $screenCount;            # for screenshot naming
my $sel;
my $browser;
my %user;
my %config;

# this starts a selenium instance and a browser
sub startBrowser(){
    ($browser, %config) = @_;

    $screenCount = 1;
    $sel = Test::WWW::Selenium->new(   host => $config{'host'},                # your host
                                       port => $config{'port'},                # port
                                       browser => "*$browser",                 # the asterisk is necessary for selenium
                                       browser_url => $config{'browser_url'},  # url of the loncapa server you want to test
                                      );
    $sel->open('/');        # if you want to maximize you first have to open a page
    $sel->wait_for_page_to_load($maxTimeout);
    $sel->window_maximize() if $config{'maximize'};
    # $sel->set_speed(1000);
    return $sel;
}

sub endBrowser(){
    $sel->stop();
    $sel = 0;
}

sub getActiveBrowser(){
    return $sel;
}

# Login for loncapa
sub login(){
    %user = @_;

    # have a clean start
    logout();

    $sel->open('/adm/roles');
    $sel->wait_for_page_to_load($maxTimeout);

    if($sel->get_title() =~ /login/i){
        $sel->type("id=uname", $user{'user'});
        $sel->type('//div[2]/div/form/input[4]', $user{'pw'});
        $sel->submit('name=client');

    }else{
        print "Title of page: ".$sel->get_title();
        print "Bail out! Something went wrong";
    }

    # skip "entering $coursename..." page:
    $sel->pause(3000);
}

# Simple Logout
sub logout(){
    $sel->open('/adm/logout');
    $sel->wait_for_page_to_load($maxTimeout);
}

sub getProblemXML_Maxima(){
   return <<END;
<problem>
<formularesponse id="214">
<answergroup type="ordered">
<answer name="both" type="ordered">
<value>1</value> <value>2</value> <value>3</value> <value>4</value><value>5</value>
</answer>
</answergroup>
<textline readonly="no"></textline>
<textline readonly="no"></textline>
<textline readonly="no"></textline>
<textline readonly="no"></textline>
<textline readonly="no"></textline>
</formularesponse>
</problem>
END
}


# creates a screenshot (of the whole screen!) and names it automatically
sub takeScreenshot(){
    return if $config{'no_screenshots'};
    my $comment = shift;

    my $bname = $browser;
    # remove path from browser name
    if($bname =~ m/ /){
        $bname =~ s/(^.*?) .*$/$1/;
    }

    my $picture_name;
    if($comment){
        $picture_name = "$screenCount - $comment.png";
    }else{
        $picture_name = "$screenCount.png";
    }

    if($config{'screenshot_folders'}){
        $sel->capture_screenshot("screenshots/$bname/$picture_name");
        print "            Screenshot captured (screenshots/$bname/$picture_name)\n";
    }else{
        $sel->capture_screenshot("screenshots/$bname $picture_name");
        print "            Screenshot captured (screenshots/$bname $picture_name)\n";
    }
    $screenCount += 1;
}
1;

Index: modules/goltermann/Tests/config.cfg
+++ modules/goltermann/Tests/config.cfg
# LONCAPA Test Suite configuration files

# --- LONCAPA Configuration --------------------------------
# domain of test environment
domain=fhwfdev2

# name of testuser
user=TestUser1

# password of testuser
pw=testuser1

# --- Selenium Config --------------------------------------
# address of your test system
host=141.41.35.158

# port of your test system
port=4444

# address of your LONCAPA server
browser_url=http://141.41.35.157/

# --- Customization ----------------------------------------
# to speed things up and skip some tests
fast=1

# maximize the browser window on the test system
# it is recommended to maximize the window if you are taking screenshots
# because the whole screen will be captured, not the browser window
maximize=1

# disable screenshots
no_screenshots=0

# create a new screenshot folder for every browser
screenshot_folders=1

Index: modules/goltermann/Tests/runTests.pl
+++ modules/goltermann/Tests/runTests.pl
#!perl
use strict;
use warnings;
use Test::More 0.98;
use Smart::Comments;
use lib('/home/httpd/lib/perl','.','./t');

# -- LONCAPA Testsuite --
# This will run several automated tests for the lonnet module and tests lon capa in different browsers.
# During certains tests screenshots will be captured. These Screenshots are stored where your selenium server is located.
# You can deactivate this feature in the config file
#
# If you want to write your own test module you have to give your module an explicit package name.
# Also the module needs a run() function which contains all the tests included in your module.
# It is recommended to start with the Template.pm to create a your own testmodule!
# Dont forget to add it to the module list below!
#
# --- START of CONFiGURATiON -----------------------------------------------------------------------
# package names of modules you want to test:
my @internalTestModules = ('UserRelated');                  # internal tests
my @browserTestModules = ('ProblemTest','InterfaceTest');   # browser tests
#
# specify path on host machine for browser selenium server cannot find
# you sometimes might need to add pathes for other browser
my $pathToChrome='C:\Program Files\Google\Chrome\Application\chrome.exe';
#
# order of the browsers you want to test
my @browsers=('firefox',"googlechrome $pathToChrome",'safari','iexplore');
# my @browsers=('safari');

my %config;
loadConfig();
# --- END of CONFiGURATiON ------------------------------------------------------------------------

# TODO: cvs commit

print "\nLON-CAPA testing script v0.25-Alpha\nPlease read documentation.\n\n";

my $selenium_unavailable = 0;
checkPrerequisites();

if($selenium_unavailable){
     print "No Selenium tests possible. Continue anyway? [y/n]\n";
        if (<STDIN> =~ 'n') {
            die 'Aborted by user';
        }
}

# starting the clock
my $startTime = time();

runInternalTests();
runBrowserTests() unless $selenium_unavailable; # to spare you all the error messages

# end of script
sub checkPrerequisites {

    subtest "internal prerequisites" => sub {

        use_ok('Apache::lonnet');
        use_ok('Apache::Tests::Util');
        # checking if test user is valid
        ok(&Apache::lonnet::authenticate($config{'user'},$config{'pw'},$config{'domain'}) ne 'no_host', 'test user existing');

    } or die 'Error. there is no use in running more tests';

    subtest "external prerequisites" => sub {

        use_ok('WWW::Selenium');
        use_ok('Test::WWW::Selenium');

    } or $selenium_unavailable = 1;
}

sub runInternalTests {
    foreach my $module (@internalTestModules){
        print "\nTesting $module\n";
        subtest "module $module" => sub {
            use_ok($module);
            $module->run(%config);
        };
    }# end of foreach modules
}

sub runBrowserTests {
    my $sel;
    print "Some tests will be skiped due to fast mode\n" if $config{'fast'};
    foreach my $browser (@browsers){
        print "\nstarting $browser\n";
        $sel = &Util::startBrowser($browser, %config);

        subtest 'testrun in '.$browser => sub {

            foreach my $module (@browserTestModules){
                subtest 'module '.$module => sub {
                    use_ok($module);
                    $module->run(%config);
                }
            }
        };
        &Util::endBrowser();
    }
    $sel->stop($sel) if $sel;
}

sub loadConfig {
    my @toHash;
    open FILE, "<config.cfg" or die $!;
    while(<FILE>){
        if( $_ =~ /^[a-z]/){
            @toHash = split(/=/,$_);
            $toHash[1] =~ s/\s//g;
            $config{$toHash[0]} = "$toHash[1]";
           # print $toHash[0]."=>".$config{$toHash[0]};
        }
    }
    close FILE;
}

END{
    done_testing();

    my $testtime = time()-$startTime;
    my $h = ($testtime/60/60) % 24;
    my $m = ($testtime/60) % 60;
    my $s = $testtime % 60;

    print "Testing finished after $h h $m m $s s\n";
}

Index: modules/goltermann/internalTest/t/InterfaceTest.pm
+++ modules/goltermann/internalTest/t/InterfaceTest.pm
#!perl
use strict;
use warnings;
package InterfaceTest;
use Test::More;
use Test::WWW::Selenium;


my $maxTimeout = 30000;
my $sel;


# for now this only sends a internal msg to yourself and checks if this arrived
sub run(){
    shift; # _important_ to have the right hash to work with
    my %config = @_;

    &Util::login(%config);
    &sendmessage(%config);
}

# send and recieve of internal messages
sub sendmessage{

    $sel = Util::getActiveBrowser();
    my %config = @_;
    my $user = $config{'user'};

    my $address = $sel->{'browser_url'};        # url stem from selenium instance
    my $timestamp = localtime;
    my $uniqueText = 'Dies ist eine Testnachricht.';

    # send a mail
    $sel->open($address.'adm/email?compose=individual');
    $sel->wait_for_page_to_load($maxTimeout);
    $sel->type('recuname', $user);
    $sel->type('subject', $timestamp);
    $sel->type('message', $uniqueText);
    &Util::takeScreenshot('send mail interface');
    $sel->click_ok('send', undef, 'mail sent');
    $sel->pause(2000);

    # check for new mail and get value
    ok($sel->get_html_source() =~ m/<a href="\/adm\/email\?display=(.*?)&.*?>$timestamp/i, 'mail recieved');

    my $clickme = $1;
    &Util::takeScreenshot('recieved mails');

    # delete mail with saved value
    $sel->click_ok("name=delmark value=$clickme", undef, 'checkbox for mail set');
    $sel->click_ok("name=go", undef, 'mail deleted');
    $sel->wait_for_page_to_load($maxTimeout);
    $sel->pause(5000);
}
1;

Index: modules/goltermann/internalTest/t/ProblemTest.pm
+++ modules/goltermann/internalTest/t/ProblemTest.pm
#!perl
use strict;
use warnings;
package ProblemTest;
use Test::More;
use Test::WWW::Selenium;
# use Smart::Comments;

my $problemname = 'uniqueTestProb.problem';
my $maxTimeout = 30000;
my $oldConstrSpace = 1;              #set this if you use the old construction space (<version_2_11_X)

my $sel;
my %config;
my $user;
my $pass;
my $dom;

# runs all tests
sub run(){
    shift; # get rid of foreign package name, _important_ to have the right hash to work with
    %config = @_;

    $sel = Util::getActiveBrowser();

    # makes code easier to read and tidier
    $user = $config{'user'};
    $pass = $config{'pw'};
    $dom = $config{'domain'};

    # start your test functions here:
    &testLogins();
    &createProblem();

    TODO: {
        local $TODO = "This test might fail because LONCAPA times out randomly";
        &testMaxima();
    };

    &cleanup();
}

sub testLogins(){

    &badLogin();

    &Util::login(%config);
    ok($sel->get_html_source() !~ /href="\/adm\/loginproblems.html"/, 'Login');
}

# Creates an empty problem
# Contains 3 tests
sub createProblem(){

# check if previous login was ok

    $sel->open('/adm/roles');
    $sel->wait_for_page_to_load($maxTimeout);
    &Util::takeScreenshot('available roles');
    $sel->click("//input[\@name='au".$dom."']", undef, 'rolechoice author');
    $sel->wait_for_page_to_load($maxTimeout);

    if($oldConstrSpace){
        $sel->open("/priv/$user/");
    }else{
        $sel->open("/priv/$dom/$user/");
    }
    $sel->wait_for_page_to_load($maxTimeout);
    &Util::takeScreenshot('construction space');
    $sel->select('css=select[name="action"]', 'value=newproblemfile');
    $sel->type('name=newfilename', $problemname);

    # Test1: create .problem file:
    $sel->click_ok('//span/input[3]', undef, 'creating problem file');
    $sel->wait_for_page_to_load($maxTimeout);
    &Util::takeScreenshot('problem file creation');

    # Test 2: confirm problem creation
    if($sel->get_html_source() =~ m/LC_warning/){
        # if test problem already exists
        # print "Bail out! $problemname already exists. cancel to prevent data loss." unless $override;
        $sel->click_ok('css=input[type="submit"]', undef, "$problemname overwritten");
    }else{
        # else select blank template
        $sel->click('css=input[type="submit"]');
        $sel->wait_for_page_to_load($maxTimeout);

        $sel->check("//input[\@value='/home/httpd/html/res/adm/includes/templates/blank.problem']");
        $sel->click_ok('name=newfile', undef, 'chose blank problem template');
    }

    # $sel->wait_for_page_to_load($maxTimeout);
}

# Inserts the XML of a maxima problem
# Contains 2 tests
sub testMaxima(){

    return if $config{'fast'};
    my $maxproblemxml = &Util::getProblemXML_Maxima();

    # open problem in editor [Test 1]
    if($oldConstrSpace){
        $sel->open_ok("/priv/$user/$problemname?forceedit=1", undef, 'open XML editor');
    }else{
        $sel->open_ok("/priv/$dom/$user/$problemname?editmode=Edit&problemmode=editxml", undef, 'open XML editor');
    }
    $sel->wait_for_page_to_load($maxTimeout);

    # Paste problem xml
    $sel->type('name=editxmltext',$maxproblemxml);
    &Util::takeScreenshot('xml editor');

    # [Test 2] finish creating problem
    $sel->click('name=subsaveview');
    $sel->wait_for_page_to_load($maxTimeout);
    # ok if no error message
    &Util::takeScreenshot('finish problem creation');
    unlike($sel->get_html_source(), qr/<span class="LC_error">/, 'create problem');

    # calculate 20 answers, this may take a while
    $sel->click('//div[3]/span/input');
    $sel->pause(1000);

    # waiting time per problem * nr problem * 1000ms:
    $sel->wait_for_page_to_load(2.5*20*1000); #~2.5sec per answer should be fine. if there is a timeout it takes 10sec per timed out answer
}

# Deletes the created problem
# Contains 1 test
sub cleanup(){

    if($oldConstrSpace){
        $sel->open("/priv/$user/$problemname");
    }else{
        $sel->open("/priv/$dom/$user/$problemname");
    }
    $sel->wait_for_page_to_load($maxTimeout);

    # clicking the delete button
    if($oldConstrSpace){
        $sel->click('//li[4]/a/span');
    }else{
        $sel->click('//ul/li[4]/a/span');
    }
    $sel->wait_for_page_to_load($maxTimeout);

    # now delete problem
    $sel->click_ok("css=input[type='submit']", undef, 'cleanup done');
    $sel->wait_for_page_to_load($maxTimeout);
}

# Login with bad pw
# Contains 2 tests
sub badLogin(){
    return if $config{'fast'};
    # page opens
    &Util::logout();
    # TODO: loncontrol, httpd ausschalten
    $sel->open_ok('/adm/roles', undef, 'login page online');
    $sel->wait_for_page_to_load($maxTimeout);
    $sel->pause(1000);    # stabalize safari
    $sel->type('id=uname', $user);

    # # TODO: alles kaka, einfach timestamp oder so verwenden
    # my $wrongpw = '§wo at 1g3_f5z??w"i#f'; # wrong password
    # # making sure that this is not an actual password...
    # if ($pass ne $wrongpw) {
    #     $sel->type('//div[2]/div/form/input[4]', $wrongpw);
    # }else{
    #     $sel->type('//div[2]/div/form/input[4]', 'somethingdifferent');
    # }
    my $wrongpw = localtime; # a wrong password
    $sel->submit('name=client');
    $sel->wait_for_page_to_load($maxTimeout);
    # ok if no link to loginproblems help page
    ok($sel->get_html_source() =~ /href="\/adm\/loginproblems.html"/, 'bad password rejected');
    &Util::takeScreenshot('login failed');
}


1;

Index: modules/goltermann/Tests/template/Template.pm
+++ modules/goltermann/Tests/template/Template.pm
#!perl
use strict;
use warnings;
package Template;
use Test::Simple;



# optional
BEGIN{
    # e.g. getting running selenium instance # OMG nein! bad example, causes bugs! dont do it
    # but using BEGIN blocks might be useful for some other things
}


# mandatory!
sub run(){
    shift; # you need this if you pass a hash between different packages when using $module->run();
    my($sel, %config) = @_;

    # call your testfunctions here

    # please logout after inBrowser testing, leave it tidy for the person (/test) after you
}


sub myTestFunction(){
    print 'Hi there';
}

# optional
END{
    # e.g. logout
}

1;


More information about the LON-CAPA-cvs mailing list