includes example and test; new command echo

master
Marc Wäckerlin 9 years ago
parent 4f0af7e32a
commit da6971ad0e
  1. 2
      ax_init_standard_project.m4
  2. 4
      configure.ac
  3. 33
      examples/SwissSign_Silver_CA_-_G2.pem
  4. 21
      examples/makefile.am
  5. 65
      examples/test-commands.wt
  6. 2
      makefile.am
  7. 75
      src/commands.hxx
  8. 15
      src/webrunner.cxx

@ -216,7 +216,7 @@ clean-standard-project-targets:
-rm \${PACKAGE_TARNAME}-\${PACKAGE_VERSION}.tar.gz
distclean-standard-project-targets:
-rm -r autom4te.cache
-rm aclocal.m4 config.guess config.sub configure depcomp compile install-sh ltmain.sh makefile missing mkinstalldirs
-rm aclocal.m4 config.guess config.sub configure depcomp compile install-sh ltmain.sh makefile missing mkinstalldirs test-driver
maintainer-clean-standard-project-targets:
-rm makefile.in
#### End: $0

@ -9,7 +9,7 @@
# change this:
m4_define(x_package_name, webtester) # project's name
m4_define(x_major, 2) # project's major version
m4_define(x_minor, 0) # project's minor version
m4_define(x_minor, 1) # project's minor version
# never edit this block:
m4_include(ax_init_standard_project.m4)
@ -25,7 +25,7 @@ AX_USE_DOXYGEN
AX_USE_DEBIAN_PACKAGING
#AX_USE_RPM_PACKAGING
#AX_USE_CPPUNIT
#AX_BUILD_EXAMPLES
AX_BUILD_EXAMPLES
# qt features
AX_REQUIRE_QT([QT], [QtCore QtGui QtNetwork QtWebKit],

@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE
BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu
IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow
RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY
U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv
Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br
YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF
nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH
6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt
eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/
c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ
MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH
HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf
jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6
5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB
rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c
wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB
AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp
WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9
xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ
2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ
IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8
aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X
em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR
dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/
OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+
hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy
tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
-----END CERTIFICATE-----

@ -0,0 +1,21 @@
## @id $Id$
#
# This file has been added by bootstrap.sh on Sat, 10 October 2015 12:52:56 +0200
# Feel free to change it or even remove and rebuild it, up to your needs
#
## 1 2 3 4 5 6 7 8
## 45678901234567890123456789012345678901234567890123456789012345678901234567890
AM_CPPFLAGS = -I${top_srcdir}/src -I${top_builddir}/src
AM_LDFLAGS = -L${abs_top_builddir}/src/.libs
LDADD = -lwebtester
TESTS = test-commands.wt
TEST_EXTENSIONS = .wt
WT_LOG_COMPILER = ${top_builddir}/src/webrunner
AM_WT_LOG_FLAGS = -x test-output.xml -p ${srcdir}
EXTRA_DIST = ${TESTS} SwissSign_Silver_CA_-_G2.pem
CLEANFILES = test-output.xml attachments
MAINTAINERCLEANFILES = makefile.in attachments

@ -0,0 +1,65 @@
## @file This is a test script to test and to show the features of the webtester framework.
testsuite Test WebTester Commands
testcase Test Certificate Load
# Load a SwissSign root certificate, so that it is accepted in the
# following tests. Normally this is only necessary if you use
# self-signed certificates, that are unknown by qt.
ca-certificate SwissSign_Silver_CA_-_G2.pem
testcase Test Variable Definition
# set a variable to a value
set ARG4 = Argument number 4
# set a variable to the output of a system command
set WORKDIR
execute pwd
testcase Test Function Call
# call a test function with three comma separated arguments
# - either with single quotes, allmust be quoted
call test '1', 'hello world', 'here is a comma, so it must be quoted', 'ARG4'
# - or with double quotes, but the two types cannot be mixed
call test "2", "hello world", "here's a comma, so it must be quoted", "ARG4"
# - or with no quotes
call test 3, hello world, here's no comma and no quotes, ARG4
testcase Test Function Definition
## Just a test function
## @param ARG1 an argument
## @param ARG2 another argument
## @param ARG3 another argument
## @param ARG4 another argument
function test ARG1, ARG2, ARG3, ARG4
if ARG1 = 1
# this is the first function call (or at leas declared to be the first)
echo This is the first call of function "test"
echo called funtion test ARG1, ARG2, ARG3, ARG4
testcase Test Checks
# check comparisions of values
# fist set some variables to test
set TEXT = Hello world, this is a test.
set TWO = 2
# then so some checks
check TWO = 2
check 2 = TWO
check TWO = TWO
check TEXT = Hello world, this is a test.
check TEXT ^ hello world
check TEXT ~ [hH]ello.*test
check TEXT ~ world
check 1 < TWO
check TWO < 3
check 3 > TWO
testcase Test Setting Clicktype
# there are two clicktypes:
# - normal javascript this.click(); call
# - Qt emulated real mouse click
clicktype realmouse
clicktype javascript
testcase Test Load Client Certificate
# define a client certificate to authenticate to a server
#client-certificate certfile.pem keyfile.pem mypassword

@ -6,4 +6,4 @@
## 1 2 3 4 5 6 7 8
## 45678901234567890123456789012345678901234567890123456789012345678901234567890
SUBDIRS = src scripts doc
SUBDIRS = src scripts doc examples

@ -455,8 +455,25 @@ class Script: public QObject {
"command starts at the begin of a new line. Empty lines are allowed. "
"Lines that start with \"#\" are treated as comments."
"\n\n"
"Subcommands are indented. The first indented line defines the level of "
"indentation. All following lines must be indented by the same level."
"\n\n"
"Note: When a selector is required as parameter, then the selector "
"is a CSS selector that must not contain spaces.";
"is a CSS selector."
"\n\n"
"Thanks to the filter script doxygen-webtester.sed, you cab use the "
"comments for producing doxygen documenation. Just start comments with "
"\"##\" to import them to doxygen. This script is automatically configured, "
"when you use the autotools bootstrap from:\n"
"https://dev.marc.waeckerlin.org/redmine/projects/bootstrap-build-environment";
}
/// set workdir
void path(QString path) {
_path = (path.size()?path:".")+QDir::separator();
}
/// get workdir
QString path() {
return _path;
}
QString commands(Formatting f = PLAIN) const {
QString cmds;
@ -959,6 +976,7 @@ class Script: public QObject {
std::shared_ptr<xml::Node> _testsuites; ///< only valid within run
QString _testclass;
Command* _command;
QString _path;
};
class Do: public Command {
@ -1289,7 +1307,13 @@ class Upload: public Command {
Logger log(this, script);
TestWebPage* page(dynamic_cast<TestWebPage*>(frame->page()));
assert(page);
QString filename(script->replacevars(_filename));
QString filename(script->path()+script->replacevars(_filename));
if (!QFileInfo(filename).exists()) {
QStringList files(QFileInfo(filename).dir()
.entryList(QStringList(filename)));
if (files.size()==1) filename=files[0];
}
if (!QFileInfo(filename).exists()) filename=script->replacevars(_filename);
if (!QFileInfo(filename).exists()) {
QStringList files(QFileInfo(filename).dir()
.entryList(QStringList(filename)));
@ -1751,7 +1775,8 @@ class CaCertificate: public Command {
bool execute(Script* script, QWebFrame*) {
Logger log(this, script);
QString filename(script->replacevars(_filename));
QFile cacertfile(filename);
QFile cacertfile(script->path()+filename);
if (!cacertfile.exists()) cacertfile.setFileName(filename); // try without path
if (!cacertfile.exists() || !cacertfile.open(QIODevice::ReadOnly))
throw FileNotFound(filename);
QSslCertificate cacert(&cacertfile);
@ -1797,7 +1822,8 @@ class ClientCertificate: public Command {
sslConfig.setProtocol(QSsl::AnyProtocol);
sslConfig.setPeerVerifyMode(QSslSocket::AutoVerifyPeer);
QString filename(script->replacevars(_certfile));
QFile certfile(filename);
QFile certfile(script->path()+filename);
if (!certfile.exists()) certfile.setFileName(filename);
if (!certfile.exists() || !certfile.open(QIODevice::ReadOnly))
throw FileNotFound(filename);
QSslCertificate cert(&certfile);
@ -1951,7 +1977,7 @@ class Function: public Command {
" quotes. If you need a comma within a value, you must quote.";
}
QString command() const {
return tag()+" "+_name+" "+_vars.join(" ");
return tag()+" "+_name+" "+_vars.join(", ");
}
std::shared_ptr<Command> parse(Script* script, QString args,
QStringList& in, QString file, int line,
@ -2161,7 +2187,7 @@ class Check: public Command {
}
QString description() const {
return
tag()+" <value1> <op> <value2>\n"+
tag()+" <value1> <cmp> <value2>\n"+
tag()+" <value1>\n"
" <command>"
"\n\n"
@ -2169,7 +2195,12 @@ class Check: public Command {
" result of a command. The command should be a command that produces an"
" output, such as <do>, which returns the result of JavaScript or"
" <execute>, which returns the output of the executed command, or"
" <call>, which returns the result of the last command.";
" <call>, which returns the result of the last command. "
"The comparision <cmp> can be = ^ ~ < >, "
"which means equal, different, match, "
"less (as integer), bigger (as integer). "
"Match allows a regular expression. "
" less than < (integers), larger than > (integers)";
}
QString command() const {
if (_next)
@ -2270,6 +2301,35 @@ class For: public Command {
std::shared_ptr<Script> _script;
};
class Echo: public Command {
public:
QString tag() const {
return "echo";
}
QString description() const {
return
tag()+" <text>"
"\n\n"
"Echoes a text to the log.";
}
QString command() const {
return tag();
}
std::shared_ptr<Command> parse(Script*, QString args,
QStringList&, QString, int, int) {
std::shared_ptr<Echo> cmd(new (Echo));
cmd->_text = args;
return cmd;
}
bool execute(Script* script, QWebFrame* frame) {
Logger log(this, script);
log(script->replacevars(_text));
return true;
}
public:
QString _text;
};
/* Template:
class : public Command {
public:
@ -2393,6 +2453,7 @@ inline void Script::initPrototypes() {
add(new TestCase);
add(new Check);
add(new For);
add(new Echo);
}
#endif

@ -52,14 +52,17 @@ using namespace NAMESPACE;
*/
QString format(QString txt, int indent = 2, int cpl = 60) {
QString format(QString txt, int indent = 2, int cpl = 80) {
QStringList res;
QStringList lines(txt.split('\n'));
QString ind(indent, ' ');
Q_FOREACH(QString line, lines) {
line.insert(0, ind);
for (int pos(0); line.size()-pos>cpl; ++pos) {
pos=line.lastIndexOf(' ', pos+cpl);
for (int pos(indent); line.size()-pos>cpl; ++pos) {
int pos2=line.lastIndexOf(' ', pos+cpl);
if (pos2>pos) pos=pos2;
else pos=line.indexOf(' ', pos+1);
if (pos<0) break;
line.remove(pos, 1);
line.insert(pos, "\n"+ind);
}
@ -102,6 +105,9 @@ int main(int argc, char *argv[]) try {
Script script;
parser.setApplicationDescription(help(script));
parser.addHelpOption();
parser.addOption(QCommandLineOption
(QStringList()<<"p"<<"path",
"search <path> within the test scripts", "path"));
parser.addOption(QCommandLineOption
(QStringList()<<"x"<<"xml",
"store XML output in <xmlfile>", "xmlfile"));
@ -133,6 +139,7 @@ int main(int argc, char *argv[]) try {
<<" built on "<<build_date()<<std::endl;
return 0;
}
if (parser.isSet("path")) script.path(parser.value("path"));
int retries(parser.value("retries").toInt());
int width(parser.value("width").toInt());
int height(parser.value("height").toInt());
@ -186,6 +193,7 @@ int main(int argc, char *argv[]) try {
script.log("SUCCESS: "+file);
}
} catch (std::exception& e) {
failed = true;
script.log("FAILED: "+file+" with "+e.what());
xml::Node failure("failure");
failure.attr("message") = Script::xmlattr(e.what()).toStdString();
@ -201,7 +209,6 @@ int main(int argc, char *argv[]) try {
testcase<<failure;
for (int i(testsuites->last().children()); i<expectedtestcases; ++i)
testsuites->last()<<testcase;
failed = true;
}
}
if (expectedtestcases==-1) {

Loading…
Cancel
Save