This commit is contained in:
ghendricks%novell.com 2006-12-20 17:01:20 +00:00
Родитель 840041b3f5
Коммит cbbc6cf43a
35 изменённых файлов: 1583 добавлений и 487 удалений

Просмотреть файл

@ -104,6 +104,11 @@ use constant DB_COLUMNS => qw(
test_cases.alias
);
use constant ALIAS_MAX_LENGTH => 255;
use constant REQUIREMENT_MAX_LENGTH => 255;
use constant SUMMARY_MAX_LENGTH => 255;
use constant TAG_MAX_LENGTH => 255;
our $columns = join(", ", DB_COLUMNS);
sub display_columns {

Просмотреть файл

@ -169,7 +169,7 @@ sub _init {
detaint_natural($case_id) || return undef;
$obj = $dbh->selectrow_hashref(
"SELECT $columns FROM test_case_runs
WHERE case__id = ?
WHERE case_id = ?
AND run_id = ?
AND build_id = ?
AND environment_id = ?",
@ -274,6 +274,7 @@ sub switch {
my $oldenv = $self->{'environment_id'};
$self = Bugzilla::Testopia::TestCaseRun->new($self->clone($build_id,$env_id));
$self->set_as_current;
if ($oldbuild != $build_id){
my $build = Bugzilla::Testopia::Build->new($build_id);
@ -292,7 +293,6 @@ sub switch {
$self->append_note($note);
}
}
$self->set_as_current;
return $self;
}

Просмотреть файл

@ -87,6 +87,8 @@ use constant DB_COLUMNS => qw(
test_plans.isactive
);
use constant NAME_MAX_LENGTH => 255;
our $columns = join(", ", DB_COLUMNS);
sub report_columns {
@ -151,7 +153,7 @@ sub _init {
} else {
ThrowCodeError('bad_arg',
{argument => 'param',
function => 'Testopia::TestRun::_init'});
function => 'Testopia::TestPlan::_init'});
}
return undef unless (defined $obj);
@ -781,6 +783,7 @@ Returns the id of the type name passed.
=cut
sub lookup_type_by_name {
my $self = shift;
my ($name) = @_;
my $dbh = Bugzilla->dbh;

Просмотреть файл

@ -24,22 +24,14 @@ Bugzilla::Testopia::Xml - Testopia Xml object
=head1 DESCRIPTION
This module parsers a XML representation of a Testopia test plan,
test case, test environment, category or build and returns Testopia
objects re
This module parsers a XML representation of a Testopia Test Plans,
Test Cases, or Categories and stores them in Testopia if not errors
are detected.
=head1 SYNOPSIS
use Bugzilla::Testopia::Xml;
=head1 SEE ALSO
Testopia::(TestPlan, TestCase, TestRun, Category, Build, Environment)
=head1 AUTHOR
David Koenig <dkoenig@novell.com>
=cut
package Bugzilla::Testopia::Xml;
@ -62,6 +54,26 @@ use Bugzilla::Testopia::XmlTestCase;
use Bugzilla::User;
use Bugzilla::Util;
###############################
#### Initialization ####
###############################
=head1 CONSTANTS
=over 4
=item STRIP_NONE - Do not strip white space from string.
=item STRIP_LEFT - Strip white space from left side of string.
=item STRIP_RIGHT - Strip white space from right side of string.
=item STRIP_BOTH - Strinp white space from left and right side of string.
=back
=cut
use constant AUTOMATIC => "AUTOMATIC";
use constant BLOCKS => "blocks";
our $DATABASE_DESCRIPTION = "Database_descripiton";
@ -70,6 +82,10 @@ use constant IGNORECASE => 1;
use constant DEPENDSON => "dependson";
use constant PCDATA => "#PCDATA";
use constant REQUIRE => "REQUIRE";
use constant STRIP_NONE => 0;
use constant STRIP_LEFT => 1;
use constant STRIP_RIGHT => 2;
use constant STRIP_BOTH => 3;
our $TESTOPIA_GT = "&testopia_gt;";
our $TESTOPIA_LT = "&testopia_lt;";
use constant TESTPLAN_REFERENCE => "testplan_reference";
@ -83,7 +99,6 @@ our $XML_QUOT = "&[Qq][Uu][Oo][Tt];";
use constant XMLREFERENCES_FIELDS => "Database_descripiton Database_id Xml_description";
@Bugzilla::Testopia::Xml::EXPORT = qw($DATABASE_DESCRIPTION $DATABASE_ID $XML_DESCRIPTION);
use Class::Struct;
#
# The Xml structure is used to keep track of all new Testopia objects being created.
@ -101,7 +116,7 @@ struct
#TODO testenvironments => '@',
# Array of testcases read from xml source.
testcases => '@',
# Hash of testcase aliases indexed by testcase id. Used during verfication to
# Hash of testcase aliases indexed by testcase summary. Used during verfication to
# insure that alias does not exist and that new aliases are used in only one testcase.
testcase_aliases => '%',
# Array of testplans read from xml source.
@ -116,94 +131,24 @@ struct
use Text::Diff;
###############################
#### Initialization ####
###############################
=head1 FIELDS
=cut
###############################
#### Methods ####
###############################
sub debug_display()
{
my ($self) = @_;
=head1 METHODS
foreach my $category ( @{$self->categories})
{
bless($category,"Bugzilla::Testopia::Category");
print STDERR "Category: " . $category->name() . "\n";
my $category_id = "null";
$category_id = $category->id() if ( $category->id() );
print STDERR " ID " . $category_id . "\n";
print STDERR " Product ID " . $category->product_id() . "\n";
print STDERR " Description " . $category->description() . "\n";
}
=over 4
foreach my $testplan ( @{$self->testplans} )
{
bless($testplan,"Bugzilla::Testopia::TestPlan");
print STDERR "Testplan: " . $testplan->name() . "\n";
my $testplan_id = "null";
$testplan_id = $testplan->id() if ( $testplan->id() );
print STDERR " ID " . $testplan_id . "\n";
my %author = %{$testplan->author()};
my $author_id = $author{"id"};
my $author_login = $author{"login"};
print STDERR " Author " . $author_login . " (id=" . $author_id . ", hash=" . $testplan->author() . ")\n";
print STDERR " Creation Date " . $testplan->creation_date() . "\n";
print STDERR " Description " . $testplan->text() . "\n";
print STDERR " Default Product Version " . $testplan->product_version() . "\n";
print STDERR " Document " . $testplan->text() . "\n";
print STDERR " Is Active " . $testplan->isactive() . "\n";
print STDERR " Product " . $testplan->product_id() . "\n";
print STDERR " Type " . $testplan->type_id() . "\n";
foreach my $tag ( @{$self->tags} )
{
print STDERR " Tag " . $tag . "\n";
}
my @attachments = @{$testplan->attachments()};
foreach my $attachment (@attachments)
{
my %submitter = %{$testplan->submitter()};
my $author_login = $author{"login"};
print STDERR " Attachment " . $attachment->description() . "\n";
print STDERR " Creation Date " . $attachment->creation_ts(). "\n";
print STDERR " Filename " . $attachment->filename() . "\n";
print STDERR " Mime Type " . $attachment->mime_type(). "\n";
print STDERR " Submitter " . $author_login . "\n";
}
}
foreach my $testcase ( @{$self->testplans} )
{
bless($testcase,"Bugzilla::Testopia::XmlTestCase");
$testcase->debug_display();
}
}
=item C<entity_replace_testopia($string,$strip)>
=head2 entity_replace_testopia
Replace testopia entities in the string supplied.
This method is called for any field that is stored in HTML format. The Testopia entities are
provided to allow users to pass HTML tags.
For example, if you want to store a < in Bold font, the following XML
&testopia_lt;B&testopia_gt;&lt;&testopia_lt;/B&testopia_gt;
is passed to the HTML field as
<B>&lt;</B>
Description: This method is called for any field that is stored in HTML format. The Testopia
entities are provided to allow users to pass HTML tags. For example, if you want to
store a < in Bold font, the following XML
&testopia_lt;B&testopia_gt;&lt;&testopia_lt;/B&testopia_gt;
is passed to the HTML field as
<B>&lt;</B>
Params: $string - String to convert.
Returns: converted string.
=cut
@ -220,22 +165,33 @@ sub entity_replace_testopia
return $string;
}
=head2 entity_replace_xml
=pod
Replace xml entities in the string supplied.
=item C<entity_replace_xml($string,$strip)>
This method is called for any field that is not stored in HTML format. The source is XML so any
XML entity will be in the &<name>; format. These entities need to be converted back to their
character representation.
Description: This method is called for any field that is not stored in HTML format. The source
is XML so any XML entity will be in the &<name>; format. These entities need to be
converted back to their character representation.
Params: $string - String to convert.
$strip - STRIP_NONE, STRIP_LEFT, STRIP_RIGHT, or STRIP_BOTH. White space stripping
is included because MySQL 5.0.3 retains trailing spaces when values are
stored and retrieved while prior versions stripped the trailing spaces.
Any non HTML field should use STRIP_BOTH to prevent searching issues if the
database was orginally pre MySQL 5.0.3.
Returns: converted string.
=back
=cut
sub entity_replace_xml
{
my ($string) = @_;
my ($string,$strip) = @_;
return undef if ( ! defined $string );
$string =~ s/^\s+// if ( $strip & STRIP_LEFT );
$string =~ s/\s+$// if ( $strip & STRIP_RIGHT );
$string =~ s/$XML_GT/>/g;
$string =~ s/$XML_LT/</g;
$string =~ s/$XML_AMP/&/g;
@ -287,9 +243,9 @@ sub parse()
foreach my $twig_category ($root->children('category'))
{
my $category_name = $twig_category->field('name');
my $product_name = $twig_category->att('product');
my $description = $twig_category->field('description');
my $category_name = entity_replace_xml($twig_category->field('name'),STRIP_BOTH);
my $product_name = entity_replace_xml($twig_category->att('product'),STRIP_BOTH);
my $description = entity_replace_xml($twig_category->field('description'),STRIP_BOTH);
$description = "FIX ME. Created during category import with no description supplied." if ( $description eq "" );
@ -351,22 +307,26 @@ sub parse()
$self->error("Cannot find product '" . $twig_testplan->field('product') . "' in test plan '" . $twig_testplan->field('name') . "'.");
}
my $name = entity_replace_xml($twig_testplan->field('name'),STRIP_BOTH) || undef;
$self->error("Found empty Test Plan name.") if ( ! defined($name) );
$self->error("Length of Test Plan name '" . $name . "' must be " . Bugzilla::Testopia::TestPlan->NAME_MAX_LENGTH . " characters or less.") if ( defined($name) && ( length($name) > Bugzilla::Testopia::TestPlan->NAME_MAX_LENGTH ) );
$testplan = Bugzilla::Testopia::TestPlan->new({
'name' => entity_replace_xml($twig_testplan->field('name')),
'name' => $name,
'product_id' => $product_id,
'default_product_version' => entity_replace_xml($twig_testplan->field('productversion')),
'default_product_version' => entity_replace_xml($twig_testplan->field('productversion'),STRIP_BOTH),
'type_id' => $plantype_ids{$twig_testplan->att('type')},
'text' => entity_replace_testopia($twig_testplan->field('document')),
'author_id' => $author_id,
'isactive' => entity_replace_xml($twig_testplan->field('archive')),
'creation_date' => entity_replace_xml($twig_testplan->field('created'))
'isactive' => entity_replace_xml($twig_testplan->field('archive'),STRIP_BOTH),
'creation_date' => entity_replace_xml($twig_testplan->field('created'),STRIP_BOTH)
});
push @{$self->testplans}, $testplan;
my @tags = $twig_testplan->children('tag');
foreach my $twig_tag (@tags)
{
push @{$self->tags}, entity_replace_xml($twig_tag->text());
push @{$self->tags}, entity_replace_xml($twig_tag->text(),STRIP_BOTH);
}
my @attachments = $twig_testplan->children('attachment');
@ -388,11 +348,11 @@ sub parse()
$submitter_id = $submitter_user->id();
}
my $attachment = Bugzilla::Testopia::Attachment->new({
'description' => entity_replace_xml($twig_attachments->field('description')),
'filename' => entity_replace_xml($twig_attachments->field('filename')),
'description' => entity_replace_xml($twig_attachments->field('description'),STRIP_BOTH),
'filename' => entity_replace_xml($twig_attachments->field('filename'),STRIP_BOTH),
'submitter_id' => $submitter_id,
'mime_type' => entity_replace_xml($twig_attachments->field('mimetype')),
'contents' => entity_replace_xml($twig_attachments->field('data'))
'mime_type' => entity_replace_xml($twig_attachments->field('mimetype'),STRIP_BOTH),
'contents' => entity_replace_xml($twig_attachments->field('data'),STRIP_BOTH)
});
push @{$self->attachments}, $attachment;
}
@ -414,7 +374,9 @@ sub parse()
}
foreach my $twig_testcase ($root->children('testcase'))
{
my $summary = entity_replace_xml($twig_testcase->field('summary')) || undef;
my $summary = entity_replace_xml($twig_testcase->field('summary'),STRIP_BOTH) || undef;
$self->error("Found empty Test Case summary.") if ( ! defined($summary) );
$self->error("Length of summary '" . $summary . "' must be " . Bugzilla::Testopia::TestCase->SUMMARY_MAX_LENGTH . " characters or less.") if ( defined($summary) && ( length($summary) > Bugzilla::Testopia::TestCase->SUMMARY_MAX_LENGTH ) );
my $author = $twig_testcase->att('author');
# Bugzilla::User::match returns a array with a user hash. Fields of the hash needed
# are 'id' and 'login'.
@ -430,7 +392,7 @@ sub parse()
bless($author_user,"Bugzilla::User");
$author_id = $author_user->id();
}
my $tester = entity_replace_xml($twig_testcase->field('defaulttester'));
my $tester = entity_replace_xml($twig_testcase->field('defaulttester'),STRIP_BOTH);
# Bugzilla::User::match returns a array with a user hash. Fields of the hash needed
# are 'id' and 'login'.
my $tester_ref = Bugzilla::User::match($tester, 1, 0);
@ -453,12 +415,15 @@ sub parse()
$xml_testcase->dependson(Bugzilla::Testopia::XmlReferences->new(IGNORECASE, XMLREFERENCES_FIELDS));
$xml_testcase->testplan(Bugzilla::Testopia::XmlReferences->new(IGNORECASE, XMLREFERENCES_FIELDS));
push @{$self->testcases}, $xml_testcase;
my $alias = entity_replace_xml($twig_testcase->field('alias')) || undef;
my $alias = entity_replace_xml($twig_testcase->field('alias'),STRIP_BOTH) || undef;
$self->error("Length of alias '" . $alias . "' in test case '" . $summary . "' must be " . Bugzilla::Testopia::TestCase->ALIAS_MAX_LENGTH . " characters or less.") if ( defined($alias) && ( length($alias) > Bugzilla::Testopia::TestCase->ALIAS_MAX_LENGTH ) );
my $requirement = entity_replace_xml($twig_testcase->field('requirement'),STRIP_BOTH) || undef;
$self->error("Length of requirement '" . $requirement . "' in test case '" . $summary . "' must be " . Bugzilla::Testopia::TestCase->REQUIREMENT_MAX_LENGTH . " characters or less.") if ( defined($requirement) && ( length($requirement) > Bugzilla::Testopia::TestCase->REQUIREMENT_MAX_LENGTH ) );
$xml_testcase->testcase(Bugzilla::Testopia::TestCase->new({
'action' => entity_replace_testopia($twig_testcase->field('action')),
'alias' => $alias,
'arguments' => entity_replace_xml($twig_testcase->field('arguments')),
'arguments' => entity_replace_xml($twig_testcase->field('arguments'),STRIP_NONE),
'author_id' => $author_id,
'blocks' => undef,
'breakdown' => entity_replace_testopia($twig_testcase->field('breakdown')),
@ -470,9 +435,9 @@ sub parse()
'isautomated' => ( uc $twig_testcase->att('automated') ) eq AUTOMATIC,
'plans' => undef,
'priority_id' => $priority_ids{$twig_testcase->att('priority')},
'requirement' => entity_replace_xml($twig_testcase->field('requirement')),
'requirement' => $requirement,
'setup' => entity_replace_testopia($twig_testcase->field('setup')),
'script' => entity_replace_xml($twig_testcase->field('script')),
'script' => entity_replace_xml($twig_testcase->field('script'),STRIP_NONE),
'summary' => $summary,
}));
foreach my $twig_testplan_reference ( $twig_testcase->children(TESTPLAN_REFERENCE) )
@ -484,7 +449,11 @@ sub parse()
. $twig_testplan_reference->att('type')
. "' in test case '" . $twig_testcase->field('summary') . "'." );
}
elsif ( ! $xml_testcase->testplan->add($twig_testplan_reference->att('type'),entity_replace_xml($testplan_reference)) )
elsif ( length($testplan_reference) > Bugzilla::Testopia::TestPlan->NAME_MAX_LENGTH )
{
$self->error("Length of Test Plan name '" . $testplan_reference . "' for test case '" . $summary . "' must be " . Bugzilla::Testopia::TestCase->REQUIREMENT_MAX_LENGTH . " characters or less.");
}
elsif ( ! $xml_testcase->testplan->add($twig_testplan_reference->att('type'),entity_replace_xml($testplan_reference,STRIP_BOTH)) )
{
$self->error("Do not know how to handle test plan of type '"
. $twig_testplan_reference->att('type')
@ -493,11 +462,11 @@ sub parse()
}
}
# Keep track of this testcase's alias. Used during verification to insure aliases are unique.
$self->testcase_aliases(entity_replace_xml($twig_testcase->field('summary')),$alias) if ( defined $alias );
$self->testcase_aliases(entity_replace_xml($twig_testcase->field('summary'),STRIP_BOTH),$alias) if ( defined $alias );
# Keep track of this testcase's category. To create a category at this time would require
# getting the product from the Test Plan that this Test Case is associated with. The category
# will created when each Test Case is stored.
$xml_testcase->category(entity_replace_xml($twig_testcase->field('categoryname')));
$xml_testcase->category(entity_replace_xml($twig_testcase->field('categoryname'),STRIP_BOTH));
my @attachments = $twig_testcase->children('attachment');
foreach my $twig_attachments (@attachments)
@ -518,11 +487,11 @@ sub parse()
$submitter_id = $submitter_user->id();
}
my $attachment = Bugzilla::Testopia::Attachment->new({
'description' => entity_replace_xml($twig_attachments->field('description')),
'filename' => entity_replace_xml($twig_attachments->field('filename')),
'description' => entity_replace_xml($twig_attachments->field('description'),STRIP_BOTH),
'filename' => entity_replace_xml($twig_attachments->field('filename'),STRIP_BOTH),
'submitter_id' => $submitter_id,
'mime_type' => entity_replace_xml($twig_attachments->field('mimetype')),
'contents' => entity_replace_xml($twig_attachments->field('data'))
'mime_type' => entity_replace_xml($twig_attachments->field('mimetype'),STRIP_BOTH),
'contents' => entity_replace_xml($twig_attachments->field('data'),STRIP_BOTH)
});
$xml_testcase->add_attachment($attachment);
}
@ -530,19 +499,21 @@ sub parse()
my @tags = $twig_testcase->children('tag');
foreach my $twig_tag ( @tags )
{
$xml_testcase->add_tag(entity_replace_xml($twig_tag->text()));
my $tag = entity_replace_xml($twig_tag->text(),STRIP_BOTH);
$self->error("Length of tag '" . $tag . "' in test case '" . $summary . "' must be " . Bugzilla::Testopia::TestCase->TAG_MAX_LENGTH . " characters or less.") if ( defined($tag) && ( length($tag) > Bugzilla::Testopia::TestCase->TAG_MAX_LENGTH ) );
$xml_testcase->add_tag($tag);
}
my @components = $twig_testcase->children('component');
foreach my $twig_component ( @components )
{
my $results = $xml_testcase->add_component(entity_replace_xml($twig_component->children_text(PCDATA)),$twig_component->att('product'));
my $results = $xml_testcase->add_component(entity_replace_xml($twig_component->children_text(PCDATA),STRIP_BOTH),$twig_component->att('product'));
$self->error($results) if ( $results ne "" );
}
foreach my $twig_blocks ( $twig_testcase->children(BLOCKS) )
{
if ( ! $xml_testcase->blocks->add($twig_blocks->att('type'),entity_replace_xml($twig_blocks->children_text(PCDATA))) )
if ( ! $xml_testcase->blocks->add($twig_blocks->att('type'),entity_replace_xml($twig_blocks->children_text(PCDATA),STRIP_BOTH)) )
{
$self->error("Do not know how to handle a blocking test case of type '" . $twig_blocks->att('type') . "' in test case '" . $xml_testcase->testcase->summary() . "'.")
}
@ -550,9 +521,9 @@ sub parse()
foreach my $twig_dependson ( $twig_testcase->children(DEPENDSON) )
{
if ( ! $xml_testcase->dependson->add($twig_dependson->att('type'),entity_replace_xml($twig_dependson->children_text(PCDATA))) )
if ( ! $xml_testcase->dependson->add($twig_dependson->att('type'),entity_replace_xml($twig_dependson->children_text(PCDATA),STRIP_BOTH)) )
{
$self->error("Do not know how to handle dependency of type '" . $twig_dependson->att('type') . "' in test case '" . entity_replace_xml($xml_testcase->testcase->summary()) . "'.")
$self->error("Do not know how to handle dependency of type '" . $twig_dependson->att('type') . "' in test case '" . entity_replace_xml($xml_testcase->testcase->summary(),STRIP_BOTH) . "'.")
}
}
}
@ -623,8 +594,14 @@ sub parse()
# Store new categories.
foreach my $category ( @{$self->categories} )
{
# Make sure category still does not exist. We don't check for uniqueness above so
# the same category could be defined multiple times.
if ( ! $category->check_name($category->name()) )
{
$category->store();
print "Created category '" . $category->name() . "': " . $category->description() . "\n";
my $product_name = Bugzilla::Testopia::Product->new($category->product_id())->name();
print "Created category '" . $category->name() . "': " . $category->description() . " for product " . $product_name . ".\n";
}
}
# Store new testplans.
@ -673,4 +650,14 @@ sub parse()
$twig->purge;
}
=head1 SEE ALSO
Testopia::(TestPlan, TestCase, TestRun, Category, Build, Environment)
=head1 AUTHOR
David Koenig <dkoenig@novell.com>
=cut
1;

Просмотреть файл

@ -258,6 +258,14 @@ sub get_testcase_ids()
return @return_testcase_id;
}
=head2 store
Saves a imported Test Case. This method insures that all Test Case attributes not stored
in the Test Case object are created. The attributes include the Test Plan, tags, compoents,
attachments and categories.
=cut
sub store()
{
my ($self, @new_testplans) = @_;
@ -359,20 +367,49 @@ sub store()
return $error_message;
}
=head2 store_relationships
Save the dependson and blocks relationships between Test Cases. This method can only be
called after the Test Cases being imported have been stored. The dependson and blocks
relationships use the Test Case identifier which is created only after the Test Case has
been stored.
=cut
sub store_relationships()
{
my ($self, @new_testcases) = @_;
my $blocks = join(' ',$self->get_testcase_ids("blocks",@new_testcases));
my $dependson = join(' ',$self->get_testcase_ids("dependson",@new_testcases));
# Hashes are used because the entires in blocks and dependson must be unique.
my %blocks = ();
foreach my $block ( $self->get_testcase_ids("blocks",@new_testcases) )
{
$blocks{$block}++;
}
my $blocks_size = keys( %blocks );
my %dependson = ();
foreach my $dependson ( $self->get_testcase_ids("dependson",@new_testcases) )
{
$dependson{$dependson}++;
}
my $dependson_size = keys( %dependson );
if ( $blocks ne "" || $dependson ne "" )
if ( ( $blocks_size > 0 ) || ( $dependson_size > 0 ) )
{
# Need to add the current blocks and dependson from the Test Case; otherwise, they will
# be removed.
$blocks .= $self->testcase->blocked_list_uncached();
$dependson .= $self->testcase->dependson_list_uncached();
$self->testcase->update_deps($dependson,$blocks);
foreach my $block ( split(/ /,$self->testcase->blocked_list_uncached()) )
{
$blocks{$block}++;
}
foreach my $dependson ( split(/ /,$self->testcase->dependson_list_uncached()) )
{
$dependson{$dependson}++;
}
my @blocks = keys(%blocks);
my @dependson = keys(%dependson);
$self->testcase->update_deps( join(' ',@dependson ),join(' ',@blocks) );
}
}

Просмотреть файл

@ -23,6 +23,94 @@ use base qw(Bugzilla::WebService);
use Bugzilla::Testopia::Build;
sub get
{
my $self = shift;
my ($build_id) = @_;
$self->login;
#Result is a test plan hash map
my $build = new Bugzilla::Testopia::Build($build_id);
if (not defined $build)
{
$self->logout;
die "Build, " . $build_id . ", not found";
}
$self->logout;
return $build;
}
sub create
{
my $self = shift;
my ($new_values) = @_; # Required: name, product_id
$self->login;
my $build = new Bugzilla::Testopia::Build($new_values);
my $name = $$new_values{name};
if (defined($name) && $build->check_name($name))
{
die "Build name, " . $name . ", already exists";
}
my $result = $build->store();
$self->logout;
# Result is new build id
return $result;
}
sub update
{
my $self =shift;
my ($build_id, $new_values) = @_; # Modifiable: name, description, milestone
$self->login;
my $build = new Bugzilla::Testopia::Build($build_id);
if (not defined $build)
{
$self->logout;
die "Build, " . $build_id . ", not found";
}
my $name = $$new_values{name};
if (defined($name) && $build->check_name($name))
{
die "Build name, " . $name . ", already exists";
}
if (!defined($name))
{
$name = $build->name();
}
my $description = (defined($$new_values{description}) ? $$new_values{description} : $build->description());
my $milestone = (defined($$new_values{milestone}) ? $$new_values{milestone} : $build->milestone());
my $result = $build->update($name,
$description,
$milestone);
$build = new Bugzilla::Testopia::Build($build_id);
$self->logout;
# Result is modified build, otherwise an exception will be thrown
return $build;
}
sub lookup_name_by_id
{
my $self = shift;

Просмотреть файл

@ -0,0 +1,171 @@
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
# Dallas Harken <dharken@novell.com>
package Bugzilla::WebService::Testopia::Environment;
use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::Testopia::Environment;
use Bugzilla::Testopia::Search;
use Bugzilla::Testopia::Table;
# Utility method called by the list method
sub _list
{
my ($query) = @_;
my $cgi = Bugzilla->cgi;
$cgi->param("current_tab", "environment");
foreach (keys(%$query))
{
$cgi->param($_, $$query{$_});
}
my $search = Bugzilla::Testopia::Search->new($cgi);
# Result is an array of environment hash maps
return Bugzilla::Testopia::Table->new('environment',
'tr_xmlrpc.cgi',
$cgi,
undef,
$search->query()
)->list();
}
sub get
{
my $self = shift;
my ($environment_id) = @_;
$self->login;
#Result is a environment hash map
my $environment = new Bugzilla::Testopia::Environment($environment_id);
if (not defined $environment)
{
$self->logout;
die "Environment, " . $environment_id . ", not found";
}
if (not $environment->canview)
{
$self->logout;
die "User Not Authorized";
}
$self->logout;
return $environment;
}
sub list
{
my $self = shift;
my ($query) = @_;
$self->login;
my $list = _list($query);
$self->logout;
return $list;
}
sub create
{
my $self =shift;
my ($new_values) = @_;
$self->login;
my $environment = new Bugzilla::Testopia::Environment($new_values);
my $result = $environment->store();
$self->logout;
# Result is new environment id
return $result;
}
sub update
{
my $self =shift;
my ($environment_id, $new_values) = @_;
$self->login;
my $environment = new Bugzilla::Testopia::Environment($environment_id);
if (not defined $environment)
{
$self->logout;
die "Environment, " . $environment_id . ", not found";
}
if (not $environment->canedit)
{
$self->logout;
die "User Not Authorized";
}
my $result = $environment->update($new_values);
$environment = new Bugzilla::Testopia::Environment($environment_id);
$self->logout;
# Result is modified environment, otherwise an exception will be thrown
return $environment;
}
sub get_runs
{
my $self = shift;
my ($environment_id) = @_;
$self->login;
my $environment = new Bugzilla::Testopia::Environment($environment_id);
if (not defined $environment)
{
$self->logout;
die "Environment, " . $environment_id . ", not found";
}
if (not $environment->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $environment->runs();
$self->logout;
# Result is list of test runs for the given environment
return $result;
}
1;

Просмотреть файл

@ -20,89 +20,10 @@ package Bugzilla::WebService::Testopia::TestCase;
use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::User;
use Bugzilla::Util qw(detaint_natural);
use Bugzilla::Testopia::TestCase;
use Bugzilla::Testopia::Search;
use Bugzilla::Testopia::Table;
# Convert string field values to their respective integer id's
sub _convert_to_ids
{
my ($hash) = @_;
if (defined($$hash{"author"}))
{
$$hash{"author_id"} = login_to_id($$hash{"author"});
}
delete $$hash{"author"};
if (defined($$hash{"case_status"}))
{
$$hash{"case_status_id"} = Bugzilla::Testopia::TestCase::lookup_status_by_name($$hash{"case_status"});
}
delete $$hash{"case_status"};
if (defined($$hash{"category"}))
{
$$hash{"category_id"} = Bugzilla::Testopia::TestCase::lookup_category_by_name($$hash{"category"});
}
delete $$hash{"category"};
if (defined($$hash{"default_tester"}))
{
$$hash{"default_tester_id"} = login_to_id($$hash{"default_tester"});
}
delete $$hash{"default_tester"};
if (defined($$hash{"priority"}))
{
$$hash{"priority_id"} = Bugzilla::Testopia::TestCase::lookup_priority_by_value($$hash{"priority"});
}
delete $$hash{"priority"};
}
# Convert fields with integer id's to their respective string values
sub _convert_to_strings
{
my ($hash) = @_;
$$hash{"author"} = "";
if (defined($$hash{"author_id"}))
{
$$hash{"author"} = new Bugzilla::User($$hash{"author_id"})->login;
}
delete $$hash{"author_id"};
$$hash{"case_status"} = "";
if (defined($$hash{"case_status_id"}))
{
$$hash{"case_status"} = Bugzilla::Testopia::TestCase->lookup_status($$hash{"case_status_id"});
}
delete $$hash{"case_status_id"};
$$hash{"category"} = "";
if (defined($$hash{"category_id"}))
{
$$hash{"category"} = Bugzilla::Testopia::TestCase->lookup_category($$hash{"category_id"});
}
delete $$hash{"category_id"};
$$hash{"default_tester"} = "";
if (defined($$hash{"default_tester_id"}))
{
$$hash{"default_tester"} = new Bugzilla::User($$hash{"default_tester_id"})->login;
}
delete $$hash{"default_tester_id"};
$$hash{"priority"} = "";
if (defined($$hash{"priority_id"}))
{
$$hash{"priority"} = Bugzilla::Testopia::TestCase->lookup_priority($$hash{"priority_id"});
}
delete $$hash{"priority_id"};
}
# Utility method called by the list method
sub _list
{
@ -110,8 +31,6 @@ sub _list
my $cgi = Bugzilla->cgi;
$cgi->param("viewall", 1);
$cgi->param("current_tab", "case");
foreach (keys(%$query))
@ -135,42 +54,38 @@ sub get
my $self = shift;
my ($test_case_id) = @_;
Bugzilla->login;
$self->login;
# We can detaint immediately if what we get passed is fully numeric.
# We leave bug alias checks to Bugzilla::Testopia::TestCase::new.
my $test_case = new Bugzilla::Testopia::TestCase($test_case_id);
if (not defined $test_case)
{
$self->logout;
die "Testcase, " . $test_case_id . ", not found";
}
if (not $test_case->canview)
{
$self->logout;
die "User Not Authorized";
}
if ($test_case_id =~ /^[0-9]+$/) {
detaint_natural($test_case_id);
}
$self->logout;
#Result is a test case hash map
my $testcase = new Bugzilla::Testopia::TestCase($test_case_id);
_convert_to_strings($testcase);
Bugzilla->logout;
return $testcase;
return $test_case;
}
sub list
{
Bugzilla->login;
my $self = shift;
my ($query) = @_;
_convert_to_ids($query);
$self->login;
my $list = _list($query);
foreach (@$list)
{
_convert_to_strings($_);
}
Bugzilla->logout;
$self->logout;
return $list;
}
@ -180,16 +95,16 @@ sub create
my $self =shift;
my ($new_values) = @_;
Bugzilla->login;
$self->login;
_convert_to_ids($new_values);
my $test_case = new Bugzilla::Testopia::TestCase($new_values);
Bugzilla->logout;
my $result = $test_case->store();
$self->logout;
# Result is new test plan id
return $test_case->store();
return $result
}
sub update
@ -197,18 +112,30 @@ sub update
my $self =shift;
my ($test_case_id, $new_values) = @_;
Bugzilla->login;
$self->login;
my $test_case = new Bugzilla::Testopia::TestCase($test_case_id);
_convert_to_ids($new_values);
if (not defined $test_case)
{
$self->logout;
die "Testcase, " . $test_case_id . ", not found";
}
$test_case->update($new_values);
if (not $test_case->canedit)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_case->update($new_values);
$test_case = new Bugzilla::Testopia::TestCase($test_case_id);
$self->logout;
Bugzilla->logout;
# Result is zero on success, otherwise an exception will be thrown
return 0;
# Result is modified test case on success, otherwise an exception will be thrown
return $test_case;
}
sub get_text
@ -216,20 +143,25 @@ sub get_text
my $self =shift;
my ($test_case_id) = @_;
Bugzilla->login;
$self->login;
my $test_case = new Bugzilla::Testopia::TestCase($test_case_id);
if (not defined $test_case)
{
$self->logout;
die "Testcase, " . $test_case_id . ", not found";
}
if (not $test_case->canview)
{
$self->logout;
die "User Not Authorized";
}
my $doc = $test_case->text();
$$doc{"author"} = "";
if (defined($$doc{"author_id"}))
{
$$doc{"author"} = new Bugzilla::User($$doc{"author_id"})->login;
}
delete $$doc{"author_id"};
Bugzilla->logout;
$self->logout;
#Result is the latest test case doc hash map
return $doc;
@ -238,20 +170,257 @@ sub get_text
sub store_text
{
my $self =shift;
my ($test_case_id, $author, $action, $effect) = @_;
my ($test_case_id, $author_id, $action, $effect, $setup, $breakdown) = @_;
Bugzilla->login;
$self->login;
my $author_id = login_to_id($author);
my $test_case = new Bugzilla::Testopia::TestCase($test_case_id);
my $version = $test_case->store_text($test_case_id, $author_id, $action, $effect);
if (not defined $test_case)
{
$self->logout;
die "Testcase, " . $test_case_id . ", not found";
}
Bugzilla->logout;
if (not $test_case->canedit)
{
$self->logout;
die "User Not Authorized";
}
my $version = $test_case->store_text($test_case_id, $author_id, $action, $effect, $setup, $breakdown);
$self->logout;
# Result is new test case doc version on success, otherwise an exception will be thrown
return $version;
}
sub get_plans
{
my $self = shift;
my ($test_case_id) = @_;
$self->login;
my $test_case = new Bugzilla::Testopia::TestCase($test_case_id);
if (not defined $test_case)
{
$self->logout;
die "Testcase, " . $test_case_id . ", not found";
}
if (not $test_case->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_case->plans();
$self->logout;
# Result is list of test plans for the given test case
return $result;
}
sub add_component
{
my $self =shift;
my ($test_case_id, $component_id) = @_;
$self->login;
my $test_case = new Bugzilla::Testopia::TestCase($test_case_id);
if (not defined $test_case)
{
$self->logout;
die "Testcase, " . $test_case_id . ", not found";
}
if (not $test_case->canedit)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_case->add_component($component_id);
$self->logout;
# Result 0 on success, otherwise an exception will be thrown
return 0;
}
sub remove_component
{
my $self =shift;
my ($test_case_id, $component_id) = @_;
$self->login;
my $test_case = new Bugzilla::Testopia::TestCase($test_case_id);
if (not defined $test_case)
{
$self->logout;
die "Testcase, " . $test_case_id . ", not found";
}
if (not $test_case->canedit)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_case->remove_component($component_id);
$self->logout;
# Result 0 on success, otherwise an exception will be thrown
return 0;
}
sub get_components
{
my $self =shift;
my ($test_case_id) = @_;
$self->login;
my $test_case = new Bugzilla::Testopia::TestCase($test_case_id);
if (not defined $test_case)
{
$self->logout;
die "Testcase, " . $test_case_id . ", not found";
}
if (not $test_case->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_case->components();
$self->logout;
# Result list of components otherwise an exception will be thrown
return $result;
}
sub lookup_status_id_by_name
{
my $self =shift;
my ($name) = @_;
$self->login;
my $result = Bugzilla::Testopia::TestCase::lookup_status_by_name($name);
$self->logout;
# Result is test case status id for the given test case status name
return $result;
}
sub lookup_status_name_by_id
{
my $self =shift;
my ($id) = @_;
$self->login;
my $test_case = new Bugzilla::Testopia::TestCase({});
my $result = $test_case->lookup_status($id);
$self->logout;
if (!defined $result)
{
$result = 0;
};
# Result is test case status name for the given test case status id
return $result;
}
sub lookup_category_id_by_name
{
my $self =shift;
my ($name) = @_;
$self->login;
my $result = Bugzilla::Testopia::TestCase::lookup_category_by_name($name);
$self->logout;
# Result is test case category id for the given test case category name
return $result;
}
sub lookup_category_name_by_id
{
my $self =shift;
my ($id) = @_;
$self->login;
my $test_case = new Bugzilla::Testopia::TestCase({});
my $result = $test_case->lookup_category($id);
$self->logout;
if (!defined $result)
{
$result = 0;
};
# Result is test case category name for the given test case category id
return $result;
}
sub lookup_priority_id_by_name
{
my $self =shift;
my ($name) = @_;
$self->login;
my $result = Bugzilla::Testopia::TestCase::lookup_priority_by_value($name);
$self->logout;
# Result is test case priority id for the given test case priority name
return $result;
}
sub lookup_priority_name_by_id
{
my $self =shift;
my ($id) = @_;
$self->login;
my $test_case = new Bugzilla::Testopia::TestCase({});
my $result = $test_case->lookup_priority($id);
$self->logout;
if (!defined $result)
{
$result = 0;
};
# Result is test case priority name for the given test case priority id
return $result;
}
1;

Просмотреть файл

@ -18,57 +18,13 @@
package Bugzilla::WebService::Testopia::TestCaseRun;
use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::Util qw(detaint_natural);
use Bugzilla::Testopia::TestCaseRun;
use Bugzilla::User;
use Bugzilla::Testopia::Search;
use Bugzilla::Testopia::Table;
# Convert string field values to their respective integer id's
sub _convert_to_ids
{
my ($hash) = @_;
if (defined($$hash{"assignee"}))
{
$$hash{"assignee"} = login_to_id($$hash{"assignee"});
}
if (defined($$hash{"testedby"}))
{
$$hash{"testedby"} = login_to_id($$hash{"testedby"});
}
if (defined($$hash{"case_run_status"}))
{
$$hash{"case_run_status_id"} = Bugzilla::Testopia::TestCaseRun::lookup_status_by_name($$hash{"case_run_status"});
}
delete $$hash{"case_run_status"};
}
# Convert fields with integer id's to their respective string values
sub _convert_to_strings
{
my ($hash) = @_;
if (defined($$hash{"assignee"}))
{
$$hash{"assignee"} = new Bugzilla::User($$hash{"assignee"})->login;
}
if (defined($$hash{"testedby"}))
{
$$hash{"testedby"} = new Bugzilla::User($$hash{"testedby"})->login;
}
$$hash{"case_run_status"} = "";
if (defined($$hash{"case_run_status_id"}))
{
$$hash{"case_run_status"} = Bugzilla::Testopia::TestCaseRun->lookup_status($$hash{"case_run_status_id"});
}
delete $$hash{"case_run_status_id"};
}
use Bugzilla::Testopia::TestCaseRun;
# Utility method called by the list method
sub _list
@ -100,21 +56,24 @@ sub get
my $self = shift;
my ($test_case_run_id) = @_;
Bugzilla->login;
# We can detaint immediately if what we get passed is fully numeric.
# We leave bug alias checks to Bugzilla::Testopia::TestCaseRun::new.
if ($test_case_run_id =~ /^[0-9]+$/) {
detaint_natural($test_case_run_id);
}
$self->login;
#Result is a test case run hash map
my $test_case_run = new Bugzilla::Testopia::TestCaseRun($test_case_run_id);
if (not defined $test_case_run)
{
$self->logout;
die "TestcaseRun, " . $test_case_run_id . ", not found";
}
if (not $test_case_run->canview)
{
$self->logout;
die "User Not Authorized";
}
_convert_to_strings($test_case_run);
Bugzilla->logout;
$self->logout;
return $test_case_run;
@ -122,21 +81,14 @@ sub get
sub list
{
Bugzilla->login;
my $self = shift;
my ($query) = @_;
_convert_to_ids($query);
$self->login;
my $list = _list($query);
foreach (@$list)
{
_convert_to_strings($_);
}
Bugzilla->logout;
$self->logout;
return $list;
}
@ -146,44 +98,128 @@ sub create
my $self =shift;
my ($new_values) = @_;
Bugzilla->login;
$self->login;
_convert_to_ids($new_values);
my $test_case_run = new Bugzilla::Testopia::TestCaseRun($new_values);
Bugzilla->logout;
my $result = $test_case_run->store();
$self->logout;
# Result is new test case run id
return $test_case_run->store();
return $result;
}
sub update
{
my $self =shift;
my ($run_id, $case_id, $build_id, $new_values) = @_;
my ($run_id, $case_id, $build_id, $environment_id, $new_values) = @_;
Bugzilla->login;
$self->login;
my $test_case_run_id = Bugzilla::Testopia::TestCaseRun::lookup_case_run_id($run_id, $case_id, $build_id);
my $test_case_run = new Bugzilla::Testopia::TestCaseRun($test_case_run_id);
my $test_case_run = new Bugzilla::Testopia::TestCaseRun($case_id,
$run_id,
$build_id,
$environment_id
);
_convert_to_ids($new_values);
if (not defined $test_case_run)
{
$self->logout;
die "TestCaseRun for build_id = " . $build_id .
", case_id = " . $case_id .
", environment_id = " . $environment_id .
", run_id = " . $run_id .
", not found";
}
if (not $test_case_run->canedit)
{
$self->logout;
die "User Not Authorized";
}
# Check to see what has changed then use set methods
$$new_values{build_id} = $build_id; # Needed by TestCaseRun's update member function
if (not defined $$new_values{environment_id})
if (defined($$new_values{assignee}))
{
$$new_values{environment_id} = $test_case_run->environment; # Needed by TestCaseRun's update member function
$test_case_run->set_assignee($$new_values{assignee});
}
if (defined($$new_values{build_id}))
{
$test_case_run->set_build($$new_values{build_id});
}
if (defined($$new_values{environment_id}))
{
$test_case_run->set_environment($$new_values{environment_id});
}
if (defined($$new_values{case_run_status_id}))
{
$test_case_run->set_status($$new_values{case_run_status_id});
}
if (defined($$new_values{notes}))
{
$test_case_run->append_note($$new_values{notes});
}
$test_case_run->update($new_values);
# Remove assignee user object and replace with just assignee id
if (ref($$test_case_run{assignee}) eq 'Bugzilla::User')
{
$$test_case_run{assignee} = $$test_case_run{assignee}->id();
}
$self->logout;
#Remove attributes we do not want to publish
delete $$test_case_run{bugs};
delete $$test_case_run{build};
delete $$test_case_run{case};
delete $$test_case_run{environment};
delete $$test_case_run{run};
Bugzilla->logout;
# Result is modified test case run on success, otherwise an exception will be thrown
return $test_case_run;
}
sub lookup_status_id_by_name
{
my $self =shift;
my ($name) = @_;
$self->login;
my $result = Bugzilla::Testopia::TestCaseRun::lookup_status_by_name($name);
$self->logout;
# Result is test case run status id for the given test case run status name
return $result;
}
sub lookup_status_name_by_id
{
my $self =shift;
my ($id) = @_;
$self->login;
my $test_case_run = new Bugzilla::Testopia::TestCaseRun({});
my $result = $test_case_run->lookup_status($id);
$self->logout;
if (!defined $result)
{
$result = 0;
};
# Result is zero on success, otherwise an exception will be thrown
return 0;
# Result is test case run status name for the given test case run status id
return $result;
}
1;

Просмотреть файл

@ -133,9 +133,11 @@ sub update
my $result = $test_plan->update($new_values);
$test_plan = new Bugzilla::Testopia::TestPlan($test_plan_id);
$self->logout;
# Result is zero on success, otherwise an exception will be thrown
# Result is modified test plan, otherwise an exception will be thrown
return $test_plan;
}
@ -222,7 +224,36 @@ sub get_categories
$self->logout;
# Result is list of test runs for the given test plan
# Result is list of categories for the given test plan
return $result;
}
sub get_builds
{
my $self =shift;
my ($test_plan_id) = @_;
$self->login;
my $test_plan = new Bugzilla::Testopia::TestPlan($test_plan_id);
if (not defined $test_plan)
{
$self->logout;
die "Testplan, " . $test_plan_id . ", not found";
}
if (not $test_plan->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_plan->product->builds();
$self->logout;
# Result is list of builds for the given test plan
return $result;
}

Просмотреть файл

@ -21,51 +21,12 @@ use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::Util qw(detaint_natural);
use Bugzilla::Product;
use Bugzilla::User;
use Bugzilla::Testopia::TestRun;
use Bugzilla::Testopia::Search;
use Bugzilla::Testopia::Table;
# Convert string field values to their respective integer id's
sub _convert_to_ids
{
my ($hash) = @_;
if (defined($$hash{"manager"}))
{
$$hash{"manager_id"} = login_to_id($$hash{"manager"});
}
delete $$hash{"manager"};
if (defined($$hash{"environment"}))
{
$$hash{"environment_id"} = Bugzilla::Testopia::TestRun::lookup_environment_by_name($$hash{"environment"});
}
delete $$hash{"environment"};
}
# Convert fields with integer id's to their respective string values
sub _convert_to_strings
{
my ($hash) = @_;
$$hash{"manager"} = "";
if (defined($$hash{"manager_id"}))
{
$$hash{"manager"} = new Bugzilla::User($$hash{"manager_id"})->login;
}
delete $$hash{"manager_id"};
$$hash{"environment"} = "";
if (defined($$hash{"environment_id"}))
{
$$hash{"environment"} = Bugzilla::Testopia::TestRun->lookup_environment($$hash{"environment_id"});
}
delete $$hash{"environment_id"};
}
# Utility method called by the list method
sub _list
{
@ -73,8 +34,6 @@ sub _list
my $cgi = Bugzilla->cgi;
$cgi->param("viewall", 1);
$cgi->param("current_tab", "run");
foreach (keys(%$query))
@ -98,42 +57,38 @@ sub get
my $self = shift;
my ($test_run_id) = @_;
Bugzilla->login;
# We can detaint immediately if what we get passed is fully numeric.
# We leave bug alias checks to Bugzilla::Testopia::TestRun::new.
if ($test_run_id =~ /^[0-9]+$/) {
detaint_natural($test_run_id);
}
$self->login;
#Result is a test run hash map
my $testrun = new Bugzilla::Testopia::TestRun($test_run_id);
my $test_run = new Bugzilla::Testopia::TestRun($test_run_id);
if (not defined $test_run)
{
$self->logout;
die "Testrun, " . $test_run_id . ", not found";
}
if (not $test_run->canview)
{
$self->logout;
die "User Not Authorized";
}
_convert_to_strings($testrun);
$self->logout;
Bugzilla->logout;
return $testrun;
return $test_run;
}
sub list
{
Bugzilla->login;
my $self = shift;
my ($query) = @_;
_convert_to_ids($query);
$self->login;
my $list = _list($query);
foreach (@$list)
{
_convert_to_strings($_);
}
Bugzilla->logout;
$self->logout;
return $list;
}
@ -143,16 +98,16 @@ sub create
my $self =shift;
my ($new_values) = @_;
Bugzilla->login;
$self->login;
_convert_to_ids($new_values);
my $test_run = new Bugzilla::Testopia::TestRun($new_values);
Bugzilla->logout;
my $result = $test_run->store();
$self->logout;
# Result is new test run id
return $test_run->store();
return $result
}
sub update
@ -160,18 +115,154 @@ sub update
my $self =shift;
my ($test_run_id, $new_values) = @_;
Bugzilla->login;
$self->login;
my $test_run = new Bugzilla::Testopia::TestRun($test_run_id);
_convert_to_ids($new_values);
if (not defined $test_run)
{
$self->logout;
die "Testrun, " . $test_run_id . ", not found";
}
$test_run->update($new_values);
if (not $test_run->canedit)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_run->update($new_values);
$test_run = new Bugzilla::Testopia::TestRun($test_run_id);
Bugzilla->logout;
$self->logout;
# Result is zero on success, otherwise an exception will be thrown
return 0;
# Result is modified test run on success, otherwise an exception will be thrown
return $test_run;
}
sub get_test_cases
{
my $self =shift;
my ($test_run_id) = @_;
$self->login;
my $test_run = new Bugzilla::Testopia::TestRun($test_run_id);
if (not defined $test_run)
{
$self->logout;
die "Testrun, " . $test_run_id . ", not found";
}
if (not $test_run->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_run->cases();
$self->logout;
# Result is list of test cases for the given test run
return $result;
}
sub get_test_case_runs
{
my $self =shift;
my ($test_run_id) = @_;
$self->login;
my $test_run = new Bugzilla::Testopia::TestRun($test_run_id);
if (not defined $test_run)
{
$self->logout;
die "Testrun, " . $test_run_id . ", not found";
}
if (not $test_run->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_run->caseruns();
$self->logout;
# Result is list of test case runs for the given test run
return $result;
}
sub get_test_plan
{
my $self =shift;
my ($test_run_id) = @_;
$self->login;
my $test_run = new Bugzilla::Testopia::TestRun($test_run_id);
if (not defined $test_run)
{
$self->logout;
die "Testrun, " . $test_run_id . ", not found";
}
if (not $test_run->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_run->plan();
$self->logout;
# Result is test plan for the given test run
return $result;
}
sub lookup_environment_id_by_name
{
my $self =shift;
my ($name) = @_;
$self->login;
my $result = Bugzilla::Testopia::TestRun::lookup_environment_by_name($name);
$self->logout;
# Result is test run environment id for the given test run environment name
return $result;
}
sub lookup_environment_name_by_id
{
my $self =shift;
my ($id) = @_;
$self->login;
my $test_run = new Bugzilla::Testopia::TestRun({});
my $result = $test_run->lookup_environment($id);
$self->logout;
if (!defined $result)
{
$result = 0;
};
# Result is test run environment name for the given test run environment id
return $result;
}
1;

Просмотреть файл

@ -25,10 +25,9 @@
[% colsepchar = user.settings.csv_colsepchar.value %]
[% PROCESS testopia/case/csv.header.tmpl %]
[% PROCESS testopia/export/csv.caseheader.tmpl %]
[% FOREACH test_case = table.list %]
[% PROCESS testopia/case/csv.case.tmpl case=test_case %]
[% END %]
[% PROCESS testopia/export/csv.case.tmpl case=test_case %]
[% END %]

Просмотреть файл

@ -197,13 +197,16 @@ found.
[% END %]
</form>
[% IF table.list_count >0 %]
<div id="buglist_actions">
<div class="links">
<span class="label">Export:</span>
<a href="tr_list_cases.cgi?
[% urlquerypart FILTER remove('&viewall=.') FILTER html %]&amp;ctype=csv&amp;viewall=1"><image src="testopia/img/csv.png" class="image"></a>
<a href="tr_list_cases.cgi?[% urlquerypart FILTER remove('&viewall=.') FILTER html %]&amp;ctype=csv&amp;viewall=1"><image src="testopia/img/csv.png" class="image"></a>
|
<a href="tr_list_cases.cgi?[% urlquerypart FILTER remove('&viewall=.') FILTER html %]&amp;ctype=xml&amp;viewall=1"><image src="testopia/img/xml.png" class="image"></a>
</div>
</div>
[% END %]
[%############################################################################%]
[%# Page Footer #%]

Просмотреть файл

@ -0,0 +1,29 @@
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Test Runner System.
#
# The Initial Developer of the Original Code is Maciej Maczynski.
# Portions created by Maciej Maczynski are Copyright (C) 2001
# Maciej Maczynski. All Rights Reserved.
#
# Contributor(s): David Koenig <dkoenig@novell.com>
#%]
[%# Testopia Show Test Case XML export template #%]
[% PROCESS testopia/export/xml.header.tmpl -%]
[% FOREACH test_case = table.list %]
[%+ PROCESS testopia/export/xml.case.tmpl case=test_case %]
[% END %]
[%- PROCESS testopia/export/xml.footer.tmpl %]

Просмотреть файл

@ -27,6 +27,6 @@
[% colsepchar = user.settings.csv_colsepchar.value %]
[% PROCESS testopia/case/csv.header.tmpl %]
[% PROCESS testopia/export/csv.caseheader.tmpl %]
[% PROCESS testopia/case/csv.case.tmpl%]
[% PROCESS testopia/export/csv.case.tmpl %]

Просмотреть файл

@ -305,8 +305,9 @@
<div id="buglist_actions">
<div class="links">
<span class="label">Export:</span>
<a href="tr_show_case.cgi?case_id=[% case.id FILTER none %]&amp;ctype=csv"><image src="testopia/img/csv.png" class="image"></a>
[%# <a href="tr_list_cases.cgi?ctype=xml"><image src="images/xml.png" class="image"></a> #%]
<a href="tr_show_case.cgi?&amp;case_id=[% case.id FILTER none %]&amp;ctype=csv"><image src="testopia/img/csv.png" class="image"></a>
|
<a href="tr_show_case.cgi?&amp;case_id=[% case.id FILTER none %]&amp;ctype=xml"><image src="testopia/img/xml.png" class="image"></a>
</div>
</div>

Просмотреть файл

@ -0,0 +1,26 @@
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Test Runner System.
#
# The Initial Developer of the Original Code is Maciej Maczynski.
# Portions created by Maciej Maczynski are Copyright (C) 2001
# Maciej Maczynski. All Rights Reserved.
#
# Contributor(s): David Koenig <dkoenig@novell.com>
#%]
[%# Testopia Show Test Case XML export template #%]
[% PROCESS testopia/export/xml.header.tmpl %]
[%+ PROCESS testopia/export/xml.case.tmpl %]
[% PROCESS testopia/export/xml.footer.tmpl %]

Просмотреть файл

@ -0,0 +1,87 @@
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Test Runner System.
#
# The Initial Developer of the Original Code is Maciej Maczynski.
# Portions created by Maciej Maczynski are Copyright (C) 2001
# Maciej Maczynski. All Rights Reserved.
#
# Contributor(s): Ed Fuentetaja <efuentetaja@acm.org>
# David Koenig <dkoenig@novell.com>
#%]
[%# Testopia Test Case CSV row export template #%]
[% PROCESS global/variables.none.tmpl %]
[% colsepchar = user.settings.csv_colsepchar.value %]
[% FOREACH column = displaycolumns %]
[% SWITCH column %]
[% CASE 'action' %]
[% case.text.action FILTER csv %]
[% CASE 'author_id' %]
[% case.author.email FILTER csv %]
[% CASE 'blocks' %]
[% case.blocked_list FILTER csv %]
[% CASE 'break_down' %]
[% case.text.breakdown FILTER csv %]
[% CASE 'case_status_id' %]
[% case.status FILTER csv %]
[% CASE 'category_id' %]
[% case.category.name FILTER csv %]
[% CASE 'components' %]
[% FILTER csv %]
[% FOREACH component = case.components %]
[% component.name %](product=[% component.product_name %])
[% IF component != case.components.last %]
[% colsepchar %]
[% END %]
[% END %]
[% END %]
[% CASE 'default_tester_id' %]
[% case.default_tester.email FILTER csv %]
[% CASE 'depends_on' %]
[% case.dependson_list FILTER csv %]
[% CASE 'expected_results' %]
[% case.text.effect FILTER csv %]
[% CASE 'isautomated' %]
[% case.isautomated ? "YES" : "NO" FILTER csv %]
[% CASE 'plans' %]
[% FILTER csv %]
[% FOREACH plan = case.plans %]
[% plan.id %]
[% IF plan != case.plans.last %]
[% colsepchar %]
[% END %]
[% END %]
[% END %]
[% CASE 'priority_id' %]
[% case.priority FILTER csv %]
[% CASE 'set_up' %]
[% case.text.setup FILTER csv %]
[% CASE 'tags' %]
[% FILTER csv %]
[% FOREACH tag = case.tags %]
[% tag.name %]
[% IF tag != case.tags.last %]
[% colsepchar %]
[% END %]
[% END %]
[% END %]
[% CASE DEFAULT %]
[% case.$column FILTER csv %]
[% END %]
[% IF column != displaycolumns.last %]
[% colsepchar %]
[% END %]
[% END %]

Просмотреть файл

@ -0,0 +1,37 @@
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Test Runner System.
#
# The Initial Developer of the Original Code is Maciej Maczynski.
# Portions created by Maciej Maczynski are Copyright (C) 2001
# Maciej Maczynski. All Rights Reserved.
#
# Contributor(s): Ed Fuentetaja <efuentetaja@acm.org>
# David Koenig <dkoenig@novell.com>
#%]
[%# Testopia Test Case CSV column header export template #%]
[% PROCESS global/variables.none.tmpl %]
[% colsepchar = user.settings.csv_colsepchar.value %]
[% FOREACH column = displaycolumns %]
[% IF column == 'case_id' %]
[% column FILTER csv %]
[% ELSE %]
[% column FILTER remove('_id') FILTER csv %]
[% END %]
[% IF column != displaycolumns.last %]
[% colsepchar %]
[% END %]
[% END %]

Просмотреть файл

@ -0,0 +1,85 @@
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Test Runner System.
#
# The Initial Developer of the Original Code is Maciej Maczynski.
# Portions created by Maciej Maczynski are Copyright (C) 2001
# Maciej Maczynski. All Rights Reserved.
#
# Contributor(s): David Koenig <dkoenig@novell.com>
#%]
[%# Testopia Test Case XML export template #%]
[% PROCESS global/variables.none.tmpl %]
<testcase author="[% case.author.email FILTER xml %]" priority="[% case.priority FILTER xml %]" automated="[% case.isautomated ? "Automatic" : "Manual" FILTER xml %]" status="[% case.status FILTER xml %]">
[% IF case.text.action %]
<action>[% case.text.action FILTER xml %]</action>
[% END %]
[% IF case.alias %]
<alias>[% case.alias FILTER xml %]</alias>
[% END %]
[% IF case.arguments %]
<arguments>[% case.arguments FILTER xml %]</arguments>
[% END %]
[% IF case.blocked %]
[% FOREACH blocked_test_case = case.blocked %]
<blocks type="Xml_description">[% blocked_test_case.summary FILTER xml %]</blocks>
[% END %]
[% END %]
[% IF case.text.breakdown %]
<breakdown>[% case.text.breakdown FILTER xml %]</breakdown>
[% END %]
[% IF case.category.name %]
<categoryname>[% case.category.name FILTER xml %]</categoryname>
[% END %]
[% IF case.components %]
[% FOREACH component = case.components %]
<component product="[% component.product_name %]">[% component.name FILTER xml %]</component>
[% END %]
[% END %]
[% IF case.default_tester.email %]
<defaulttester>[% case.default_tester.email FILTER xml %]</defaulttester>
[% END %]
[% IF case.dependson %]
[% FOREACH dependson_test_case = case.dependson %]
<dependson type="Xml_description">[% dependson_test_case.summary FILTER xml %]</dependson>
[% END %]
[% END %]
[% IF case.text.effect %]
<expectedresults>[% case.text.effect FILTER xml %]</expectedresults>
[% END %]
[% IF case.requirement %]
<requirement>[% case.requirement FILTER xml %]</requirement>
[% END %]
[% IF case.script %]
<script>[% case.script FILTER xml %]</script>
[% END %]
[% IF case.text.setup %]
<setup>[% case.text.setup FILTER xml %]</setup>
[% END %]
[% IF case.summary %]
<summary>[% case.summary FILTER xml %]</summary>
[% END %]
[% IF case.tags %]
[% FOREACH tag = case.tags %]
<tag>[% tag.name FILTER xml %]</tag>
[% END %]
[% END %]
[% IF case.plans %]
[% FOREACH test_plan = case.plans %]
<testplan_reference type="Xml_description">[% test_plan.name FILTER xml %]</testplan_reference>
[% END %]
[% END %]
</testcase>

Просмотреть файл

@ -0,0 +1,23 @@
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Test Runner System.
#
# The Initial Developer of the Original Code is Maciej Maczynski.
# Portions created by Maciej Maczynski are Copyright (C) 2001
# Maciej Maczynski. All Rights Reserved.
#
# Contributor(s): David Koenig <dkoenig@novell.com>
#%]
[%# Testopia XML export footer template #%]
</testopia>

Просмотреть файл

@ -0,0 +1,25 @@
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Test Runner System.
#
# The Initial Developer of the Original Code is Maciej Maczynski.
# Portions created by Maciej Maczynski are Copyright (C) 2001
# Maciej Maczynski. All Rights Reserved.
#
# Contributor(s): David Koenig <dkoenig@novell.com>
#%]
[%# Testopia XML export header template #%]
<?xml version="1.0" [% IF Param('utf8') %]encoding="UTF-8" [% END %]standalone="yes" ?>
<!DOCTYPE testopia SYSTEM "testopia.dtd">
<testopia version="1.1">

Просмотреть файл

@ -0,0 +1,33 @@
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Test Runner System.
#
# The Initial Developer of the Original Code is Maciej Maczynski.
# Portions created by Maciej Maczynski are Copyright (C) 2001
# Maciej Maczynski. All Rights Reserved.
#
# Contributor(s): Ed Fuentetaja <efuentetaja@acm.org>
# David Koenig <dkoenig@novell.com>
#%]
[%# Testopia Test Case list CSV export template #%]
[% PROCESS global/variables.none.tmpl %]
[% colsepchar = user.settings.csv_colsepchar.value %]
[% PROCESS testopia/export/csv.caseheader.tmpl %]
[% FOREACH test_case = table.list %]
[% PROCESS testopia/export/csv.case.tmpl case=test_case %]
[% END %]

Просмотреть файл

@ -275,6 +275,20 @@
[% END %]
</form>
[% IF case_table.list_count >0 %]
<div id="buglist_actions">
<div class="links">
[% IF case_table.list_count >0 %]
<span class="label">Export Test Cases:</span>
<a href="tr_show_plan.cgi?&amp;plan_id=[% plan.id FILTER none %]&amp;export=testcases&amp;ctype=csv&amp;viewall=1"><image src="testopia/img/csv.png" class="image"></a>
|
<a href="tr_show_plan.cgi?&amp;plan_id=[% plan.id FILTER none %]&amp;export=testcases&amp;ctype=xml&amp;viewall=1"><image src="testopia/img/xml.png" class="image"></a>
[% END %]
</div>
</div>
[% END %]
[%##### Footer #####%]
[% PROCESS global/footer.html.tmpl %]

Просмотреть файл

@ -0,0 +1,31 @@
[%# 1.0@bugzilla.org %]
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Test Runner System.
#
# The Initial Developer of the Original Code is Maciej Maczynski.
# Portions created by Maciej Maczynski are Copyright (C) 2001
# Maciej Maczynski. All Rights Reserved.
#
# Contributor(s): David Koenig <dkoenig@novell.com>
#%]
[%# Testopia Test Case list XML export template #%]
[% PROCESS global/variables.none.tmpl %]
[% PROCESS testopia/export/xml.header.tmpl -%]
[% FOREACH test_case = table.list %]
[%+ PROCESS testopia/export/xml.case.tmpl case=test_case %]
[% END %]
[%- PROCESS testopia/export/xml.footer.tmpl %]

Просмотреть файл

@ -92,7 +92,7 @@ Index: /bmo-2.22/Bugzilla/DB/Schema.pm
===================================================================
--- /bmo-2.22/Bugzilla/DB/Schema.pm 2006-01-06 07:38:42.000000000 -0700
+++ /bmo-2.22-testopia/Bugzilla/DB/Schema.pm 2006-10-04 16:28:11.000000000 -0600
@@ -1039,6 +1039,483 @@
@@ -1039,6 +1039,492 @@
version => {TYPE => 'decimal(3,2)', NOTNULL => 1},
],
},
@ -125,6 +125,8 @@ Index: /bmo-2.22/Bugzilla/DB/Schema.pm
+ ],
+ INDEXES => [
+ category_name_idx => ['name'],
+ category_product_id_name_idx => {FIELDS => [qw(product_id name)],
+ TYPE => 'UNIQUE'},
+ ],
+ },
+
@ -192,6 +194,8 @@ Index: /bmo-2.22/Bugzilla/DB/Schema.pm
+ case_run_shortkey_idx => ['sortkey'],
+ case_run_build_idx => [qw(case_run_id build_id)],
+ case_run_env_idx => [qw(case_run_id environment_id)],
+ case_run_build_env_idx => {FIELDS => [qw(run_id case_id build_id environment_id)],
+ TYPE => 'UNIQUE'},
+ ],
+ },
+
@ -507,6 +511,11 @@ Index: /bmo-2.22/Bugzilla/DB/Schema.pm
+ name => {TYPE => 'varchar(255)'},
+ description => {TYPE => 'TEXT'},
+ ],
+ INDEXES => [
+ build_name_idx => ['name'],
+ build_product_id_name_idx => {FIELDS => [qw(product_id name)],
+ TYPE => 'UNIQUE'},
+ ],
+ },
+
+ test_attachment_data => {

Просмотреть файл

@ -92,7 +92,7 @@ Index: /bmo-2.22/Bugzilla/DB/Schema.pm
===================================================================
--- /bmo-2.22/Bugzilla/DB/Schema.pm 2006-01-06 07:38:42.000000000 -0700
+++ /bmo-2.22-testopia/Bugzilla/DB/Schema.pm 2006-10-04 16:28:11.000000000 -0600
@@ -1039,6 +1039,483 @@
@@ -1039,6 +1039,492 @@
version => {TYPE => 'decimal(3,2)', NOTNULL => 1},
],
},
@ -125,6 +125,8 @@ Index: /bmo-2.22/Bugzilla/DB/Schema.pm
+ ],
+ INDEXES => [
+ category_name_idx => ['name'],
+ category_product_id_name_idx => {FIELDS => [qw(product_id name)],
+ TYPE => 'UNIQUE'},
+ ],
+ },
+
@ -192,6 +194,8 @@ Index: /bmo-2.22/Bugzilla/DB/Schema.pm
+ case_run_shortkey_idx => ['sortkey'],
+ case_run_build_idx => [qw(case_run_id build_id)],
+ case_run_env_idx => [qw(case_run_id environment_id)],
+ case_run_build_env_idx => {FIELDS => [qw(run_id case_id build_id environment_id)],
+ TYPE => 'UNIQUE'},
+ ],
+ },
+
@ -507,6 +511,11 @@ Index: /bmo-2.22/Bugzilla/DB/Schema.pm
+ name => {TYPE => 'varchar(255)'},
+ description => {TYPE => 'TEXT'},
+ ],
+ INDEXES => [
+ build_name_idx => ['name'],
+ build_product_id_name_idx => {FIELDS => [qw(product_id name)],
+ TYPE => 'UNIQUE'},
+ ],
+ },
+
+ test_attachment_data => {

Просмотреть файл

@ -188,13 +188,19 @@ sub remove_field_list
s/\342\200\235/&#8221;/g;
s/\302\251/&copy;/g;
s/\031/'/g;
s/\221/&apos;/g;
s/\222/&apos;/g;
s/\224/&apos;/g;
s/\221/&8216;/g; # left single quotation mark
s/\222/&8217;/g; # right single quotation mark
s/\223/&8220;/g; # left double quotation mark
s/\224/&8221;/g; # right double quotation mark
s/\226/-/g;
s/\341/&#224;/g; # small letter a with grave
s/\344/&#228;/g; # small letter a with diaeresis
s/\351/&#232;/g; # small letter e with grave
s/\337/&#223;/g; # beta
s/\341/&#224;/g; # small letter a with acute accent
s/\342/&#225;/g; # small letter a with grave accent
s/\344/&#228;/g; # small letter a with tilde
s/\346/&#229;/g; # small letter a with umlaut
s/\347/&#230;/g; # small ae
s/\350/&#231;/g; # small letter c cedilla
s/\351/&#232;/g; # small letter e with acute accent
s/\364/&#244;/g; # small letter o with circumflex
$line_count += 1;
@ -290,7 +296,7 @@ sub remove_field_list
my $double_quote_index = $comma_index+1;
while ( $double_quote_index<=$#chars )
{
last if ( $chars[$double_quote_index] =~ m/\S/ );
last if ( $chars[$double_quote_index] =~ m/\S/ && $chars[$double_quote_index] ne ',' );
$double_quote_index++;
}
# Is the next non-white space character a comma followed by a double quote? If yes then we
@ -318,6 +324,13 @@ sub remove_field_list
}
}
#
# This check is for empty fields, i.e. "field1",,"field2".
#
elsif ( $char eq "," && ! $in_quote_field )
{
push (@fields,"");
}
else
{
if ( $in_quote_field )
@ -440,40 +453,40 @@ map_TCDB_users(\%tcdb_user);
# Process the $field_list variable which comes from the first line of the CSV file.
#
# Format of the first line should be in the form:
# "Testcase Name","Attributes","Priority","Description","Status","Folder","Creator",
# "Owner","ResDetails","Build","InstanceID","Long Description","Pass/Fail Definition",
# "Setup Steps","Cleanup Steps","Steps"
# "Testcase Name","Attributes","Priority","Description","Folder","Creator","Owner",
# "Pass/Fail Definition","Setup Steps","Cleanup Steps","Steps"
#
# Fields currently used if they exist are:
# attributes - split apart at each comma to become a tag.
# category - category for test case.
# cleanupsteps - added to Break Down section.
# component - component for test case.
# description - summary unless testcasename is defined. added to Action section.
# description - summary unless testcasename is defined. added to Action section if -tcdb flag
# used.
# environment - split apart at each comma to become a tag.
# folder - only processed if -tcdb option is supplied. split apart at each '/'. based on each
# teams input one field becomes the category and others tags. each team defines which
# sub folders they want to use.
# longdescription - added to Action section.
# longdescription - added to Action section if -tcdb flag used.
# owner (required) - in TCDB this is a ID that is mapped to a email address from the file
# tcdbUsers.
# passfaildefinition - added to Expected Results section.
# priority - becomes the priority. I just a number P is prepended.
# resdetails - added to Action section.
# resdetails - added to Action section if -tcdb flag used.
# setupsteps - added to Set Up section.
# steps - added to Action section.
# testcasename - becomes the summary. if testcasename is not supplied the description
# is the summary. if testcasename and description are both null a error is
# generated.
# generated. added to Action section if -tcdb flag used.
#
# The order of the fields is not important. The fields supplied to Class::CSV will be in
# order found on the first line of the CSV file.
#
# The field_list returned from remove_field_list() will have:
# Change to lower case.
# Changed to lower case.
# Remove spaces.
# Remove all "'s
# Remove all /'s.'
# Remove all "s.
# Remove all /s.
#
# More sources for the CSV's other than TCDB, transform some of the column names.
@ -558,7 +571,14 @@ foreach my $line (@{$csv->lines()}) {
{
my @folder = split(/\\/,$line->folder());
print XMLOUTPUT " <tag>" . fix_entities($folder[4]) . "</tag>\n" if ( defined( $folder[4] ) );
print XMLOUTPUT " <categoryname>" . fix_entities($folder[5]) . "</categoryname>\n" if ( defined( $folder[5] ) );
if ( defined($fields{'category'}) )
{
print XMLOUTPUT " <tag>" . fix_entities($folder[5]) . "</tag>\n" if ( defined( $folder[5] ) );
}
else
{
print XMLOUTPUT " <categoryname>" . fix_entities($folder[5]) . "</categoryname>\n" if ( defined( $folder[5] ) );
}
my $fieldstart = 6;
while ( defined $folder[$fieldstart] )
{
@ -606,25 +626,28 @@ foreach my $line (@{$csv->lines()}) {
print XMLOUTPUT "</breakdown>\n";
}
print XMLOUTPUT " <action>";
if ( defined($fields{'testcasename'}) && ( $line->testcasename() ne "") )
if ( $tcdb )
{
print XMLOUTPUT "[TCDB Test Case Name]\n" if ( $tcdb );
print XMLOUTPUT fix_entities($line->testcasename());
}
if ( defined($fields{'description'}) && ( $line->description() ne "") )
{
print XMLOUTPUT "\n\n[TCDB Description]\n" if ( $tcdb );
print XMLOUTPUT fix_entities($line->description());
}
if ( defined($fields{'longdescription'}) && ( $line->longdescription() ne "") )
{
print XMLOUTPUT "\n\n[TCDB Long Description]\n" if ( $tcdb );
print XMLOUTPUT fix_entities($line->longdescription());
}
if ( defined($fields{'resdetails'}) && ( $line->resdetails() ne "") )
{
print XMLOUTPUT "\n\n[TCDB Resolution Details]\n" if ( $tcdb );
print XMLOUTPUT fix_entities($line->resdetails());
if ( defined($fields{'testcasename'}) && ( $line->testcasename() ne "") )
{
print XMLOUTPUT "[TCDB Test Case Name]\n";
print XMLOUTPUT fix_entities($line->testcasename());
}
if ( defined($fields{'description'}) && ( $line->description() ne "") )
{
print XMLOUTPUT "\n\n[TCDB Description]\n";
print XMLOUTPUT fix_entities($line->description());
}
if ( defined($fields{'longdescription'}) && ( $line->longdescription() ne "") )
{
print XMLOUTPUT "\n\n[TCDB Long Description]\n";
print XMLOUTPUT fix_entities($line->longdescription());
}
if ( defined($fields{'resdetails'}) && ( $line->resdetails() ne "") )
{
print XMLOUTPUT "\n\n[TCDB Resolution Details]\n";
print XMLOUTPUT fix_entities($line->resdetails());
}
}
if ( defined($fields{'steps'}) && ( $line->steps() ne "") )
{

Просмотреть файл

@ -366,6 +366,10 @@ sub UpdateDB {
$dbh->bz_drop_index('test_runs', 'run_id_2');
$dbh->bz_drop_index('test_runs', 'test_run_plan_id_run_id__idx');
$dbh->bz_add_index('test_builds', 'build_name_idx', ['name']);
$dbh->bz_add_index('test_builds', 'build_product_id_name_idx', {FIELDS => [qw(product_id name)], TYPE => 'UNIQUE'});
$dbh->bz_add_index('test_case_categories', 'category_product_id_name_idx', {FIELDS => [qw(product_id name)], TYPE => 'UNIQUE'});
$dbh->bz_add_index('test_case_runs', 'case_run_build_env_idx', {FIELDS => [qw(run_id case_id build_id environment_id)], TYPE => 'UNIQUE'});
$dbh->bz_add_index('test_case_tags', 'case_tags_user_idx', [qw(tag_id userid)]);
$dbh->bz_add_index('test_cases', 'test_case_requirement_idx', ['requirement']);
$dbh->bz_add_index('test_runs', 'test_run_plan_id_run_id_idx', [qw(plan_id run_id)]);

Просмотреть файл

@ -328,7 +328,7 @@ else {
my $disp = "inline";
# We set CSV files to be downloaded, as they are designed for importing
# into other programs.
if ($format->{'extension'} eq "csv")
if ( $format->{'extension'} eq "csv" || $format->{'extension'} eq "xml" )
{
$disp = "attachment";
$vars->{'displaycolumns'} = \@Bugzilla::Testopia::Constants::TESTCASE_EXPORT;

Просмотреть файл

@ -434,7 +434,7 @@ sub export {
my $disp = "inline";
# We set CSV files to be downloaded, as they are designed for importing
# into other programs.
if ($format->{'extension'} eq "csv")
if ( $format->{'extension'} eq "csv" || $format->{'extension'} eq "xml" )
{
$disp = "attachment";
$vars->{'displaycolumns'} = \@Bugzilla::Testopia::Constants::TESTCASE_EXPORT;

Просмотреть файл

@ -60,6 +60,13 @@ unless ($plan_id){
exit;
}
validate_test_id($plan_id, 'plan');
my $format = $template->get_format("testopia/plan/show", scalar $cgi->param('format'), scalar $cgi->param('ctype'));
unless ( $format->{'extension'} eq "html" ){
export($plan_id);
exit;
}
push @{$::vars->{'style_urls'}}, 'testopia/css/default.css';
my $serverpush = support_server_push($cgi);
@ -445,3 +452,34 @@ sub display {
$template->process("testopia/plan/show.html.tmpl", $vars) ||
ThrowTemplateError($template->error());
}
sub export {
my ($plan_id) = @_;
my $casequery = new Bugzilla::CGI($cgi);
$casequery->param('current_tab', 'case');
my $search = Bugzilla::Testopia::Search->new($casequery);
my $table = Bugzilla::Testopia::Table->new('case', 'tr_show_plan.cgi', $casequery, undef, $search->query);
ThrowUserError('testopia-query-too-large', {'limit' => $case_query_limit}) if $table->view_count > $case_query_limit;
$vars->{'table'} = $table;
my $disp = "inline";
# We set CSV files to be downloaded, as they are designed for importing
# into other programs.
if ( $format->{'extension'} eq "csv" || $format->{'extension'} eq "xml" )
{
$disp = "attachment";
$vars->{'displaycolumns'} = \@Bugzilla::Testopia::Constants::TESTCASE_EXPORT;
}
# Suggest a name for the bug list if the user wants to save it as a file.
my @time = localtime(time());
my $date = sprintf "%04d-%02d-%02d", 1900+$time[5],$time[4]+1,$time[3];
my $filename = "testcases-$date.$format->{extension}";
print $cgi->header(-type => $format->{'ctype'},
-content_disposition => "$disp; filename=$filename");
$template->process($format->{'template'}, $vars) ||
ThrowTemplateError($template->error());
}

Просмотреть файл

@ -46,8 +46,10 @@ my $response = Bugzilla::WebService::XMLRPC::Transport::HTTP::CGI
'TestCase' => 'Bugzilla::WebService::Testopia::TestCase',
'TestRun' => 'Bugzilla::WebService::Testopia::TestRun',
'TestCaseRun' => 'Bugzilla::WebService::Testopia::TestCaseRun',
'User' => 'Bugzilla::WebService::User',
'Product' => 'Bugzilla::WebService::Testopia::Product',
'Environment' => 'Bugzilla::WebService::Testopia::Environment',
'Build' => 'Bugzilla::WebService::Testopia::Build',
'Component' => 'Bugzilla::WebService::Component',
'User' => 'Bugzilla::WebService::User',
})
->handle;