[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