TestCaseRun, TestPlan, TestRun API changes

git-svn-id: svn://10.0.0.236/trunk@247339 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
ghendricks%novell.com
2008-03-07 23:42:07 +00:00
parent ab041effa3
commit ed4225bc46
8 changed files with 1487 additions and 855 deletions

View File

@@ -164,7 +164,7 @@ sub _check_case_text_version {
sub new {
my $invocant = shift;
my $class = ref($invocant) || $invocant;
my ($param, $run_id, $build_id, $env_id) = (@_);
my ($param, $case_id, $build_id, $env_id) = (@_);
my $dbh = Bugzilla->dbh;
# We want to be able to supply an empty object to the templates for numerous
@@ -176,11 +176,11 @@ sub new {
return $param;
}
}
elsif ($run_id && detaint_natural($run_id)
elsif ($case_id && detaint_natural($case_id)
&& $build_id && detaint_natural($build_id)
&& $env_id && detaint_natural($env_id)){
my $case_id = $param;
my $run_id = $param;
detaint_natural($case_id) || return undef;
($param) = $dbh->selectrow_array(
"SELECT case_run_id FROM test_case_runs
@@ -601,39 +601,42 @@ Attaches the specified bug to this test case-run
sub attach_bug {
my $self = shift;
my ($bug, $caserun_id) = @_;
my ($bugs, $caserun_id) = @_;
my @bugs = Bugzilla::Testopia::TestCase::_check_bugs($bugs);
$caserun_id ||= $self->{'case_run_id'};
my $dbh = Bugzilla->dbh;
$dbh->bz_lock_tables('test_case_bugs WRITE');
my ($exists) = $dbh->selectrow_array(
"SELECT bug_id
FROM test_case_bugs
WHERE case_run_id=?
AND bug_id=?",
undef, ($caserun_id, $bug));
if ($exists) {
$dbh->bz_unlock_tables();
return;
}
my ($check) = $dbh->selectrow_array(
"SELECT bug_id
FROM test_case_bugs
WHERE case_id=?
AND bug_id=?
AND case_run_id=?",
undef, ($caserun_id, $bug, undef));
if ($check){
$dbh->do("UPDATE test_case_bugs
SET test_case_run_id = ?
WHERE case_id = ?
AND bug_id = ?",
undef, ($bug, $self->{'case_run_id'}));
}
else{
$dbh->do("INSERT INTO test_case_bugs (bug_id, case_run_id, case_id)
VALUES(?,?,?)", undef, ($bug, $self->{'case_run_id'}, $self->{'case_id'}));
foreach my $bug (@bugs){
my ($exists) = $dbh->selectrow_array(
"SELECT bug_id
FROM test_case_bugs
WHERE case_run_id=?
AND bug_id=?",
undef, ($caserun_id, $bug));
if ($exists) {
$dbh->bz_unlock_tables();
return;
}
my ($check) = $dbh->selectrow_array(
"SELECT bug_id
FROM test_case_bugs
WHERE case_id=?
AND bug_id=?
AND case_run_id=?",
undef, ($caserun_id, $bug, undef));
if ($check){
$dbh->do("UPDATE test_case_bugs
SET test_case_run_id = ?
WHERE case_id = ?
AND bug_id = ?",
undef, ($bug, $self->{'case_run_id'}));
}
else{
$dbh->do("INSERT INTO test_case_bugs (bug_id, case_run_id, case_id)
VALUES(?,?,?)", undef, ($bug, $self->{'case_run_id'}, $self->{'case_id'}));
}
}
$dbh->bz_unlock_tables();
}

View File

@@ -146,7 +146,7 @@ sub _check_summary{
sub _check_manager {
my ($invocant, $login) = @_;
$login = trim($login);
return unless $login;
ThrowUserError('testopia-missing-required-field', {'field' => 'manager'}) unless $login;
if ($login =~ /^\d+$/){
$login = Bugzilla::User->new($login);
return $login->id;

View File

@@ -38,7 +38,7 @@ use strict;
use base qw(Exporter);
@Bugzilla::Testopia::Util::EXPORT = qw(get_test_field_id get_time_stamp
validate_test_id validate_selection
support_server_push
support_server_push process_list
percentage);
use Bugzilla;
@@ -202,6 +202,23 @@ sub log_activity {
}
sub process_list {
my ($ids) = @_;
my @ids;
if (ref $ids eq 'ARRAY'){
@ids = @$ids;
}
elsif ($ids =~ /,/){
@ids = split(/[\s,]+/, $ids);
}
else {
push @ids, $ids;
}
return @ids;
}
=head1 AUTHOR
Greg Hendricks <ghendricks@novell.com>

View File

@@ -10,10 +10,14 @@
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
# The Original Code is the Bugzilla Testopia System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
# Dallas Harken <dharken@novell.com>
# The Initial Developer of the Original Code is Greg Hendricks.
# Portions created by Greg Hendricks are Copyright (C) 2006
# Novell. All Rights Reserved.
#
# Contributor(s): Dallas Harken <dharken@novell.com>
# Greg Hendricks <ghendricks@novell.com>
package Bugzilla::WebService::Testopia::TestCase;
@@ -28,23 +32,6 @@ use Bugzilla::Testopia::Table;
use base qw(Bugzilla::WebService);
sub _process_list {
my ($ids) = @_;
my @ids;
if (ref $ids eq 'ARRAY'){
@ids = @$ids;
}
elsif ($ids =~ /,/){
@ids = split(/[\s,]+/, $ids);
}
else {
push @ids, $ids;
}
return @ids;
}
sub get {
my $self = shift;
my ($case_id) = @_;
@@ -92,7 +79,7 @@ sub create {
if (ref $new_values->{'plans'} eq 'ARRAY'){
push @plan_ids, @{$new_values->{'plans'}};
}
elsif ($new_values->{'plans'} =~ /^\d+$/){
elsif ($new_values->{'plans'} =~ /,/){
push @plan_ids, split(/[\s,]+/, $new_values->{'plans'});
}
@@ -130,14 +117,13 @@ sub create {
return $case;
}
sub update {
my $self = shift;
my ($ids, $new_values) = @_;
Bugzilla->login(LOGIN_REQUIRED);
my @ids = _process_list($ids);
my @ids = Bugzilla::Testopia::Util::process_list($ids);
my @cases;
foreach my $id (@ids){
@@ -233,7 +219,7 @@ sub attach_bug {
Bugzilla->login(LOGIN_REQUIRED);
my @ids = _process_list($case_ids);
my @ids = Bugzilla::Testopia::Util::process_list($case_ids);
my @results;
foreach my $id (@ids){
my $case = new Bugzilla::Testopia::TestCase($id);
@@ -294,7 +280,7 @@ sub add_component {
Bugzilla->login(LOGIN_REQUIRED);
my @ids = _process_list($case_ids);
my @ids = Bugzilla::Testopia::Util::process_list($case_ids);
my @results;
foreach my $id (@ids){
my $case = new Bugzilla::Testopia::TestCase($id);
@@ -355,7 +341,7 @@ sub add_tag {
Bugzilla->login(LOGIN_REQUIRED);
my @ids = _process_list($case_ids);
my @ids = Bugzilla::Testopia::Util::process_list($case_ids);
my @results;
foreach my $id (@ids){
my $case = new Bugzilla::Testopia::TestCase($id);
@@ -436,7 +422,7 @@ sub link_plan {
my ($case_ids, $test_plan_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
my @ids = _process_list($case_ids);
my @ids = Bugzilla::Testopia::Util::process_list($case_ids);
my @results;
foreach my $id (@ids){
my $case = new Bugzilla::Testopia::TestCase($id);
@@ -483,7 +469,7 @@ sub add_to_run {
Bugzilla->login(LOGIN_REQUIRED);
my @ids = _process_list($case_ids);
my @ids = Bugzilla::Testopia::Util::process_list($case_ids);
my @results;
foreach my $id (@ids){
my $case = new Bugzilla::Testopia::TestCase($id);
@@ -764,7 +750,7 @@ Provides methods for automated scripts to manipulate Testopia TestCases
Returns: Array: An array of case-run object hashes.
=item C<get_case_run_history($case_id)>
=item C<get_change_history($case_id)>
Description: Get the list of changes to the fields of this case.
@@ -838,11 +824,19 @@ Provides methods for automated scripts to manipulate Testopia TestCases
| author | A bugzilla login (email address) |
| author_type | (select from email_variants) |
| case_id | comma separated integers |
| case_status | String: Status |
| case_status_id | Integer: Status |
| category | String: Category Name |
| category_id | Integer |
| component | String: Component Name |
| default_tester | A bugzilla login (email address) |
| default_tester_type | (select from email_variants) |
| isautomated | 1: true 0: false |
| plan_id | comma separated integers |
| priority | String: Priority |
| priority_id | Integer |
| product | String: Product Name |
| product_id | Integer |
| requirement | String: Requirement |
| requirement_type | (select from query_variants) |
| run_id | comma separated integers |
@@ -916,17 +910,37 @@ Provides methods for automated scripts to manipulate Testopia TestCases
Returns: Array: Matching test cases are retuned in a list of hashes.
=item C<lookup_category_name_by_id> B<DEPRICATED> Use TestCase::get instead
=item C<lookup_category_id_by_name> B<DEPRICATED - CONSIDERED HARMFUL> Use TestCase::check_build instead
=item C<lookup_category_name_by_id>
Params: $id - Integer: ID of the case status to return
=item C<lookup_priority_name_by_id> B<DEPRICATED> Use TestCase::get instead
Returns: String: the status name.
=item C<lookup_priority_id_by_name> B<DEPRICATED - CONSIDERED HARMFUL> Use TestCase::check_build instead
=item C<lookup_category_id_by_name> B<DEPRICATED - CONSIDERED HARMFUL> Use check_category instead
=item C<lookup_status_name_by_id> B<DEPRICATED> Use TestCase::get instead
=item C<lookup_priority_name_by_id>
Params: $id - Integer: ID of the case status to return
Returns: String: the status name.
=item C<lookup_status_id_by_name> B<DEPRICATED - CONSIDERED HARMFUL> Use TestCase::check_build instead
=item C<lookup_priority_id_by_name>
Params: $name - String: the status name.
Returns: Integer: ID of the case status.
=item C<lookup_status_name_by_id>
Params: $id - Integer: ID of the case status to return
Returns: String: the status name.
=item C<lookup_status_id_by_name>
Params: $name - String: the status name.
Returns: Integer: ID of the case status.
=item C<remove_component($case_id, $component_id)>
@@ -961,7 +975,7 @@ Provides methods for automated scripts to manipulate Testopia TestCases
=item C<update($ids, $values)>
Description: Updates the fields of the selected build or builds.
Description: Updates the fields of the selected case or cases.
Params: $ids - Integer/String/Array
Integer: A single TestCase ID.
@@ -972,9 +986,9 @@ Provides methods for automated scripts to manipulate Testopia TestCases
$values - Hash of keys matching TestCase fields and the new values
to set each field to.
Returns: Hash/Array: In the case of a single build it is returned. If a
list was passed, it returns an array of build hashes. If the
update on any particular build failed, the has will contain a
Returns: Hash/Array: In the case of a single case it is returned. If a
list was passed, it returns an array of case hashes. If the
update on any particular case failed, the has will contain a
FAILED key and the message as to why it failed.
=back

View File

@@ -10,10 +10,14 @@
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
# The Original Code is the Bugzilla Testopia System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
# Dallas Harken <dharken@novell.com>
# The Initial Developer of the Original Code is Greg Hendricks.
# Portions created by Greg Hendricks are Copyright (C) 2006
# Novell. All Rights Reserved.
#
# Contributor(s): Dallas Harken <dharken@novell.com>
# Greg Hendricks <ghendricks@novell.com>
package Bugzilla::WebService::Testopia::TestCaseRun;
@@ -22,234 +26,611 @@ use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::User;
use Bugzilla::Constants;
use Bugzilla::Testopia::Constants;
use Bugzilla::Testopia::Search;
use Bugzilla::Testopia::Table;
use Bugzilla::Testopia::TestCaseRun;
use Bugzilla::Testopia::Util;
# Utility method called by the list method
sub _list
{
sub get {
my $self = shift;
my ($run_id, $case_id, $build_id, $env_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
#Result is a test case run hash map
my $caserun = new Bugzilla::Testopia::TestCaseRun($run_id, $case_id, $build_id, $env_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Case Run', id => $run_id}) unless $caserun;
ThrowUserError('testopia-permission-denied', {'object' => $caserun}) unless $caserun->canview;
return $caserun;
}
sub list {
my $self = shift;
my ($query) = @_;
Bugzilla->login(LOGIN_REQUIRED);
my $cgi = Bugzilla->cgi;
$cgi->param("current_tab", "case_run");
foreach (keys(%$query))
{
foreach (keys(%$query)){
$cgi->param($_, $$query{$_});
}
my $search = Bugzilla::Testopia::Search->new($cgi);
# Result is an array of test case run hash maps
return Bugzilla::Testopia::Table->new('case_run',
'tr_xmlrpc.cgi',
$cgi,
undef,
$search->query()
)->list();
return Bugzilla::Testopia::Table->new('case_run','tr_xmlrpc.cgi',$cgi,undef,$search->query())->list();
}
sub get
{
sub create {
my $self = shift;
my ($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";
}
$self->logout;
return $test_case_run;
}
sub get_bugs
{
my $self = shift;
my ($test_case_run_id) = @_;
$self->login;
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";
}
my $result = $test_case_run->bugs;
$self->logout;
# Result is list of bugs for the given test case run
return $result;
}
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) = @_;
Bugzilla->login(LOGIN_REQUIRED);
my $run = Bugzilla::Testopia::TestCaseRun->new($new_values->{'run_id'});
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Run', id => $new_values->{'run_id'}}) unless $run;
ThrowUserError('testopia-read-only', {'object' => $run}) unless $run->canedit;
if ($new_values->{'status'}){
$new_values->{'case_run_status_id'} = Bugzilla::Testopia::TestCaseRun::lookup_status_by_name($new_values->{'status'});
delete $new_values->{'status'};
}
$new_values->{'case_run_status_id'} = IDLE unless $new_values->{'case_run_status_id'};
$self->login;
my $test_case_run = Bugzilla::Testopia::TestCaseRun->create($new_values);
my $caserun = Bugzilla::Testopia::TestCaseRun->create($new_values);
$self->logout;
# Result is new test case run id
return $test_case_run->id;
# Result is new test case run object hash
return $caserun;
}
sub update
{
my $self =shift;
my ($run_id, $case_id, $build_id, $environment_id, $new_values) = @_;
sub update {
my $self = shift;
my ($run_id, $case_id, $build_id, $env_id, $new_values) = @_;
$self->login;
my $test_case_run = new Bugzilla::Testopia::TestCaseRun($case_id,
$run_id,
$build_id,
$environment_id
);
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
# The order is important. We need to check if the build or environment has
# Changed so that we can switch to the right record first.
if (defined($$new_values{build_id}))
{
$test_case_run = $test_case_run->switch($$new_values{build_id}, $environment_id ,$run_id, $case_id);
}
if (defined($$new_values{environment_id}))
{
$test_case_run = $test_case_run->switch($build_id, $$new_values{environment_id} ,$run_id, $case_id);
}
if (defined($$new_values{assignee}))
{
$test_case_run->set_assignee($$new_values{assignee});
}
if (defined($$new_values{case_run_status_id}))
{
$test_case_run->set_status($$new_values{case_run_status_id}, $$new_values{update_bugs});
}
if (defined($$new_values{notes}))
{
$test_case_run->append_note($$new_values{notes});
}
Bugzilla->login(LOGIN_REQUIRED);
# 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();
my @caseruns;
my @ids = use Bugzilla::Testopia::Util::process_list($run_id);
if (ref $case_id eq 'HASH' && !$build_id){
$new_values = $case_id;
foreach my $id (@ids){
my $caserun = new Bugzilla::Testopia::TestCaseRun($run_id);
if ($caserun){
push @caseruns, $caserun;
}
else {
push @caseruns, {FAILED => 1, message => 'Case-run does not exist'};
}
}
}
else {
foreach my $id (@ids){
my $caserun = new Bugzilla::Testopia::TestCaseRun($run_id,$case_id,$build_id,$env_id);
if ($caserun){
push @caseruns, $caserun;
}
else {
push @caseruns, {FAILED => 1, message => 'Case-run does not exist'};
}
}
}
$self->logout;
if ($new_values->{'status'}){
$new_values->{'case_run_status_id'} = Bugzilla::Testopia::TestCaseRun::lookup_status_by_name($new_values->{'status'});
delete $new_values->{'status'};
}
#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};
my @results;
foreach my $caserun (@caseruns){
if ($caserun->{'FAILED'}){
push @results, $caserun;
next;
}
unless ($caserun->canedit){
push @results, {FAILED => 1, message => "You do not have rights to edit this test case"};
next;
}
$run_id = $caserun->run_id;
$case_id = $caserun->case_id;
$build_id ||= $caserun->build_id;
$env_id ||= $caserun->env_id;
# Result is modified test case run on success, otherwise an exception will be thrown
return $test_case_run;
# Check to see what has changed then use set methods
# The order is important. We need to check if the build or environment has
# Changed so that we can switch to the right record first.
if ($new_values->{'build_id'} && $new_values->{'environment_id'}){
$caserun = $caserun->switch($new_values->{'build_id'}, $new_values->{'environment_id'}, $run_id, $case_id);
}
elsif ($new_values->{'build_id'}){
$caserun = $caserun->switch($new_values->{'build_id'}, $env_id, $run_id, $case_id);
}
elsif ($new_values->{'environment_id'}){
$caserun = $caserun->switch($build_id, $new_values->{'environment_id'}, $run_id, $case_id);
}
if ($new_values->{'assignee'}){
$caserun->set_assignee($new_values->{'assignee'});
}
if ($new_values->{'case_run_status_id'}){
$caserun->set_status($new_values->{'case_run_status_id'}, $new_values->{'update_bugs'});
}
if ($new_values->{'sortkey'}){
$caserun->set_sortkey($new_values->{'sortkey'});
}
if ($new_values->{'notes'}){
$caserun->append_note($new_values->{'notes'});
}
# Remove assignee user object and replace with just assignee id
if (ref $caserun{'assignee'} eq 'Bugzilla::User'){
$caserun{assignee} = $caserun{assignee}->id();
}
# Result is modified test case run on success, otherwise an exception will be thrown
push @results, $caserun;
}
return @results;
}
sub lookup_status_id_by_name
{
my $self =shift;
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;
Bugzilla->login(LOGIN_REQUIRED);
# Result is test case run status id for the given test case run status name
return $result;
return Bugzilla::Testopia::TestCaseRun::lookup_status_by_name($name);
}
sub lookup_status_name_by_id
{
my $self =shift;
sub lookup_status_name_by_id {
my $self = shift;
my ($id) = @_;
$self->login;
Bugzilla->login(LOGIN_REQUIRED);
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 test case run status name for the given test case run status id
return $result;
return $test_case_run->lookup_status($id);
}
sub get_history {
my $self = shift;
my ($run_id, $case_id, $build_id, $env_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
#Result is a test case run hash map
my $caserun = new Bugzilla::Testopia::TestCaseRun($run_id, $case_id, $build_id, $env_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Case Run', id => $run_id}) unless $caserun;
ThrowUserError('testopia-permission-denied', {'object' => $caserun}) unless $caserun->canview;
return $caserun->get_case_run_list;
}
sub attach_bug {
my $self = shift;
my ($run_id, $case_id, $build_id, $env_id, $bug_ids) = @_;
Bugzilla->login(LOGIN_REQUIRED);
#Result is a test case run hash map
my $caserun = new Bugzilla::Testopia::TestCaseRun($run_id, $case_id, $build_id, $env_id);
# If we have just the id, the third arg will not be set.
$bug_ids = $case_id unless $build_id;
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Case Run', id => $run_id}) unless $caserun;
ThrowUserError('testopia-read-only', {'object' => $caserun}) unless $caserun->canedit;
$caserun->attach_bug($bug_ids);
return undef;
}
sub detach_bug {
my $self = shift;
my ($run_id, $case_id, $build_id, $env_id, $bug_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
#Result is a test case run hash map
my $caserun = new Bugzilla::Testopia::TestCaseRun($run_id, $case_id, $build_id, $env_id);
# If we have just the id, the third arg will not be set.
$bug_id = $case_id unless $build_id;
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Case Run', id => $run_id}) unless $caserun;
ThrowUserError('testopia-read-only', {'object' => $caserun}) unless $caserun->canedit;
$caserun->detach_bug($bug_ids);
# Result 0 on success, otherwise an exception will be thrown
return 0;
}
sub get_bugs {
my $self = shift;
my ($run_id, $case_id, $build_id, $env_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
#Result is a test case run hash map
my $caserun = new Bugzilla::Testopia::TestCaseRun($run_id, $case_id, $build_id, $env_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Case Run', id => $run_id}) unless $caserun;
ThrowUserError('testopia-permission-denied', {'object' => $caserun}) unless $caserun->canview;
return $caserun->bugs;
}
sub get_completion_time {
my $self = shift;
my ($run_id, $case_id, $build_id, $env_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
#Result is a test case run hash map
my $caserun = new Bugzilla::Testopia::TestCaseRun($run_id, $case_id, $build_id, $env_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Case Run', id => $run_id}) unless $caserun;
ThrowUserError('testopia-permission-denied', {'object' => $caserun}) unless $caserun->canview;
return $caserun->completion_time;
}
1;
__END__
=head1 NAME
Bugzilla::Testopia::Webservice::TestCaseRun
=head1 EXTENDS
Bugzilla::Webservice
=head1 DESCRIPTION
Provides methods for automated scripts to manipulate Testopia TestCaseRuns.
=head1 SYNOPSIS
Test case-runs are the mapping of a test case in a given run for a particular
build and environment. There are therefore two ways to refer to a given
case-run:
By ID: The unique case_run_id
By Combination: $run_id, $case_id, $build_id, $environment_id
TestCaseRun methods are therefore overloaded to support either of these two
methods of looking up the case-run you are interested in.
B<EXAMPLE:>
TestCaseRun->get($caserun_id)
TestCaseRun->get($run_id, $case_id, $build_id, $environment_id)
=head1 METHODS
=over
=item C<attach_bug($caserun_id, $bug_ids)>
Description: Add one or more bugs to the selected test case-runs.
Params: $case_run_id - Integer: An integer representing the ID in the database.
$bug_ids - Integer/Array/String: An integer or alias representing the ID in the database,
an array of bug_ids or aliases, or a string of comma separated bug_ids.
Returns: undef.
=item C<attach_bug($run_id, $case_id, $build_id, $environment_id, $bug_ids)>
Description: Add one or more bugs to the selected test case-runs.
Params: $case_id - Integer: An integer representing the ID of the test case in the database.
$run_id - Integer: An integer representing the ID of the test run in the database.
$build_id - Integer: An integer representing the ID of the test build in the database.
$environment_id - Integer: An integer representing the ID of the environment in the database.
$bug_ids - Integer/Array/String: An integer or alias representing the ID in the database,
an array of bug_ids or aliases, or a string of comma separated bug_ids.
Returns: undef.
=item C<create($values)>
Description: Creates a new Test Case Run object and stores it in the database.
Params: $values - Hash: A reference to a hash with keys and values
matching the fields of the test case to be created.
Returns: The newly created object hash.
=item C<detach_bug($caserun_id, $bug_id)>
Description: Remove a bug from a test case-run.
Params: $caserun_id - Integer: An integer representing the ID in the database.
$bug_ids - Integer/Array/String: An integer or alias representing the ID in the database,
an array of bug_ids or aliases, or a string of comma separated bug_ids.
Returns: undef.
=item C<detach_bug($run_id, $case_id, $build_id, $environment_id, $bug_id)>
Description: Remove a bug from a test case-run.
Params: $case_id - Integer: An integer representing the ID of the test case in the database.
$run_id - Integer: An integer representing the ID of the test run in the database.
$build_id - Integer: An integer representing the ID of the test build in the database.
$environment_id - Integer: An integer representing the ID of the environment in the database.
$bug_id - Integer: An integer or alias representing the ID of
the bug in the database,
Returns: undef.
=item C<get($caserun_id)>
Description: Used to load an existing test case-run from the database.
Params: $caserun_id - Integer: An integer representing the ID in
the database for this case-run.
Returns: A blessed Bugzilla::Testopia::TestCase object hash
=item C<get($run_id, $case_id, $build_id, $environment_id)>
Description: Used to load an existing test case from the database.
Params: $case_id - Integer: An integer representing the ID of the test case in the database.
$run_id - Integer: An integer representing the ID of the test run in the database.
$build_id - Integer: An integer representing the ID of the test build in the database.
$environment_id - Integer: An integer representing the ID of the environment in the database.
Returns: A blessed Bugzilla::Testopia::TestCase object hash
=item C<get_bugs($caserun_id)>
Description: Get the list of bugs that are associated with this test case.
Params: $caserun_id - Integer: An integer representing the ID in
the database for this case-run.
Returns: Array: An array of bug object hashes.
=item C<get_bugs($run_id, $case_id, $build_id, $environment_id)>
Description: Get the list of bugs that are associated with this test case.
Params: $case_id - Integer: An integer representing the ID of the test case in the database.
$run_id - Integer: An integer representing the ID of the test run in the database.
$build_id - Integer: An integer representing the ID of the test build in the database.
$environment_id - Integer: An integer representing the ID of the environment in the database.
Returns: Array: An array of bug object hashes.
=item C<get_completion_time($caserun_id)>
Description: Get the list of components attached to this case.
Params: $caserun_id - Integer: An integer representing the ID in
the database for this case-run.
Returns: Array: An array of component object hashes.
=item C<get_completion_time($run_id, $case_id, $build_id, $environment_id)>
Description: Get the list of components attached to this case.
Params: $case_id - Integer: An integer representing the ID of the test case in the database.
$run_id - Integer: An integer representing the ID of the test run in the database.
$build_id - Integer: An integer representing the ID of the test build in the database.
$environment_id - Integer: An integer representing the ID of the environment in the database.
Returns: Array: An array of component object hashes.
=item C<get_history($caserun_id)>
Description: Get the list of case-runs for all runs this case appears in.
To limit this list by build or other attribute, see TestCaseRun::list.
Params: $caserun_id - Integer: An integer representing the ID in
the database for this case-run.
Returns: Array: An array of case-run object hashes.
=item C<get_history($run_id, $case_id, $build_id, $environment_id)>
Description: Get the list of case-runs for all runs this case appears in.
To limit this list by build or other attribute, see TestCaseRun::list.
Params: $case_id - Integer: An integer representing the ID of the test case in the database.
$run_id - Integer: An integer representing the ID of the test run in the database.
$build_id - Integer: An integer representing the ID of the test build in the database.
$environment_id - Integer: An integer representing the ID of the environment in the database.
Returns: Array: An array of case-run object hashes.
=item C<list($query)>
Description: Performs a search and returns the resulting list of test cases.
Params: $query - Hash: keys must match valid search fields.
+--------------------------------------------------------+
| Case-Run Search Parameters |
+--------------------------------------------------------+
| Key | Valid Values |
| andor | 1: Author AND tester, 0: OR |
| assignee | A bugzilla login (email address) |
| assignee_type | (select from email_variants) |
| build | String |
| build_id | Integer |
| case_id | comma separated integers |
| case_run_status | String: Status |
| case_run_status_id | Integer: Status |
| case_summary | String: Requirement |
| case_summary_type | (select from query_variants) |
| category | String: Category Name |
| category_id | Integer |
| component | String: Component Name |
| environment | String |
| environment_id | Integer |
| isactive | 0: Only show current 1: show all |
| isautomated | 1: true 0: false |
| milestone | String |
| notes | String |
| notes_type | (select from query_variants) |
| plan_id | comma separated integers |
| priority | String: Priority |
| priority_id | Integer |
| product | String |
| product_id | Integer |
| requirement | String: Requirement |
| requirement_type | (select from query_variants) |
| run_id | comma separated integers |
| run_product_version | String |
| run_status | 1: RUNNING 0: STOPPED |
| tags | String |
| tags_type | (select from tag_variants) |
| testedby | A bugzilla login (email address) |
| testedby_type | (select from email_variants) |
+--------------------------------------------------------+
+---------------------------------------------------+
| Paging and Sorting |
+---------------------------------------------------+
| Key | Description |
| dir | "ASC" or "DESC" |
| order | field to sort by |
+---------------------------------------------------+
| page_size | integer: how many per page |
| page | integer: page number |
| +++++++ OR +++++++ |
| start | integer: Start with which record |
| limit | integer: limit to how many |
+---------------------------------------------------+
| viewall | 1: returns all records |
+---------------------------------------------------+
+----------------------------------------------------+
| query_variants |
+----------------+-----------------------------------+
| Key | Description |
| allwordssubstr | contains all of the words/strings |
| anywordssubstr | contains any of the words/strings |
| substring | contains the string |
| casesubstring | contains the string (exact case) |
| allwords | contains all of the words |
| anywords | contains any of the words |
| regexp | matches the regexp |
| notregexp | doesn't match the regexp |
+----------------+-----------------------------------+
+-------------------------------------+
| email_variants |
+--------------+----------------------+
| Key | Description |
| substring | contains |
| exact | is |
| regexp | matches regexp |
| notregexp | doesn't match regexp |
+--------------+----------------------+
+----------------------------------------------------+
| tag_variants |
+----------------+-----------------------------------+
| Key | Description |
| anyexact | is tagged with |
| allwordssubstr | contains all of the words/strings |
| anywordssubstr | contains any of the words/strings |
| substring | contains the string |
| casesubstring | contains the string (exact case) |
| regexp | matches the regexp |
| notregexp | doesn't match the regexp |
| allwords | contains all of the words |
| anywords | contains any of the words |
| nowords | contains none of the words |
+----------------------------------------------------+
Returns: Array: Matching test cases are retuned in a list of hashes.
=item C<lookup_status_name_by_id>
Params: $id - Integer: ID of the case status to return
Returns: String: the status name.
=item C<lookup_status_id_by_name>
Params: $name - String: the status name.
Returns: Integer: ID of the case status.
=item C<update($caserun_ids, $values)>
Description: Updates the fields of the selected case-runs.
Params: $caserun_ids - Integer/String/Array
Integer: A single TestCaseRun ID.
String: A comma separates string of TestCaseRun IDs for batch
processing.
Array: An array of TestCaseRun IDs for batch mode processing
$values - Hash of keys matching TestCaseRun fields and the new values
to set each field to.
Returns: Hash/Array: In the case of a single object, it is returned. If a
list was passed, it returns an array of object hashes. If the
update on any particular object failed, the hash will contain a
FAILED key and the message as to why it failed.
=item C<update($run_id, $case_id, $build_id, $environment_id, $values)>
Description: Updates the fields of the selected case-run.
Params: $case_id - Integer: An integer representing the ID of the test case in the database.
$run_id - Integer: An integer representing the ID of the test run in the database.
$build_id - Integer: An integer representing the ID of the test build in the database.
$environment_id - Integer: An integer representing the ID of the environment in the database.
$values - Hash of keys matching TestCaseRun fields and the new values
to set each field to.
Returns: Hash/Array: In the case of a single object, it is returned. If a
list was passed, it returns an array of object hashes. If the
update on any particular object failed, the hash will contain a
FAILED key and the message as to why it failed.
=back
=head1 SEE ALSO
=over
L<Bugzilla::Testopia::TestCaseRun>
L<Bugzilla::Webservice>
=back
=head1 AUTHOR
Greg Hendricks <ghendricks@novell.com>

View File

@@ -10,10 +10,14 @@
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
# The Original Code is the Bugzilla Testopia System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
# Dallas Harken <dharken@novell.com>
# The Initial Developer of the Original Code is Greg Hendricks.
# Portions created by Greg Hendricks are Copyright (C) 2006
# Novell. All Rights Reserved.
#
# Contributor(s): Dallas Harken <dharken@novell.com>
# Greg Hendricks <ghendricks@novell.com>
package Bugzilla::WebService::Testopia::TestPlan;
@@ -28,402 +32,486 @@ use Bugzilla::Testopia::TestPlan;
use Bugzilla::Testopia::Search;
use Bugzilla::Testopia::Table;
# Utility method called by the list method
sub _list
{
sub get {
my $self = shift;
my ($plan_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
# Result is a plan object hash
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Build', id => $plan_id}) unless $plan;
ThrowUserError('testopia-permission-denied', {'object' => $plan}) unless $plan->canview;
$plan->test_run_count();
$plan->test_case_count();
return $plan;
}
sub list {
my $self = shift;
my ($query) = @_;
Bugzilla->login(LOGIN_REQUIRED);
my $cgi = Bugzilla->cgi;
$cgi->param("current_tab", "plan");
foreach (keys(%$query))
{
foreach (keys(%$query)){
$cgi->param($_, $$query{$_});
}
my $search = Bugzilla::Testopia::Search->new($cgi);
# Result is an array of test plan hash maps
return Bugzilla::Testopia::Table->new('plan',
'tr_xmlrpc.cgi',
$cgi,
undef,
$search->query()
)->list();
return Bugzilla::Testopia::Table->new('plan','tr_xmlrpc.cgi',$cgi,undef,$search->query())->list();
}
sub get
{
my $self = shift;
my ($test_plan_id) = @_;
$self->login;
#Result is a test plan hash map
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";
}
$self->logout;
return $test_plan;
}
sub list
{
my $self = shift;
my ($query) = @_;
$self->login;
my $list = _list($query);
$self->logout;
return $list;
}
sub create
{
sub create {
my $self =shift;
my ($new_values) = @_;
$self->login;
Bugzilla->login(LOGIN_REQUIRED);
my $product = Bugzilla::Testopia::Product->new($new_values->{'product_id'});
ThrowUserError('testopia-read-only', {'object' => $product}) unless $product->canedit;
my $test_plan = Bugzilla::Testopia::TestPlan->create($new_values);
my $plan = Bugzilla::Testopia::TestPlan->create($new_values);
$self->logout;
return $test_plan->id;
return $plan;
}
sub update
{
sub update {
my $self =shift;
my ($test_plan_id, $new_values) = @_;
my ($plan_id, $new_values) = @_;
$self->login;
Bugzilla->login(LOGIN_REQUIRED);
my $test_plan = new Bugzilla::Testopia::TestPlan($test_plan_id);
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
if (not defined $test_plan)
{
$self->logout;
die "Testplan, " . $test_plan_id . ", not found";
}
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Plan', id => $plan_id}) unless $plan;
ThrowUserError('testopia-read-only', {'object' => $plan}) unless $plan->canedit;
$plan->set_name(trim($new_values->{'name'}));
$plan->set_default_product_version($new_values->{'default_product_version'});
$plan->set_type($new_values->{'type_id'});
$plan->set_isactive($new_values->{'isactive'});
if (not $test_plan->canedit)
{
$self->logout;
die "User Not Authorized";
}
$plan->update();
$test_plan->set_name(trim($new_values->{'name'}));
$test_plan->set_default_product_version($new_values->{'default_product_version'});
$test_plan->set_type($new_values->{'type_id'});
$test_plan->set_isactive($new_values->{'isactive'});
$test_plan->update();
$self->logout;
# Result is modified test plan, otherwise an exception will be thrown
return $test_plan;
return $plan;
}
sub get_test_cases
{
my $self =shift;
my ($test_plan_id) = @_;
sub get_text {
my $self = shift;
my ($plan_id, $version) = @_;
$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";
}
Bugzilla->login(LOGIN_REQUIRED);
if (not $test_plan->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_plan->test_cases();
$self->logout;
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Plan', id => $plan_id}) unless $plan;
ThrowUserError('testopia-permission-denied', {'object' => $plan}) unless $plan->canview;
#Result is the latest test plan doc hash map
return $plan->text($version);
}
sub store_text {
my $self = shift;
my ($plan_id, $author_id, $text) = @_;
Bugzilla->login(LOGIN_REQUIRED);
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Plan', id => $plan_id}) unless $plan;
ThrowUserError('testopia-read-only', {'object' => $plan}) unless $plan->canedit;
my $version = $plan->store_text($plan_id, $author_id);
# Result is new test plan doc version on success, otherwise an exception will be thrown
return $version;
}
sub get_test_cases {
my $self = shift;
my ($plan_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
# Result is a plan object hash
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Build', id => $plan_id}) unless $plan;
ThrowUserError('testopia-permission-denied', {'object' => $plan}) unless $plan->canview;
# Result is list of test cases for the given test plan
return $result;
return $plan->test_cases;
}
sub get_test_runs
{
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";
}
sub get_test_runs {
my ($plan_id) = @_;
if (not $test_plan->canview)
{
$self->logout;
die "User Not Authorized";
}
Bugzilla->login(LOGIN_REQUIRED);
my $result = $test_plan->test_runs();
# Result is a plan object hash
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
$self->logout;
ThrowUserError('invalid-test-id-non-existent', {type => 'Build', id => $plan_id}) unless $plan;
ThrowUserError('testopia-permission-denied', {'object' => $plan}) unless $plan->canview;
# Result is list of test runs for the given test plan
return $result;
return $plan->test_runs;
}
sub get_categories
{
my $self =shift;
my ($test_plan_id) = @_;
sub get_change_history {
my $self = shift;
my ($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";
}
Bugzilla->login(LOGIN_REQUIRED);
if (not $test_plan->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_plan->product->categories();
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
$self->logout;
# Result is list of categories for the given test plan
return $result;
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Plan', id => $plan_id}) unless $plan;
ThrowUserError('testopia-permission-denied', {'object' => $plan}) unless $plan->canview;
# Result list of changes otherwise an exception will be thrown
return $plan->history;
}
sub get_components
{
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";
}
sub get_product {
my $self = shift;
my ($plan_id) = @_;
if (not $test_plan->canview)
{
$self->logout;
die "User Not Authorized";
}
Bugzilla->login(LOGIN_REQUIRED);
my $result = $test_plan->product->components;
# Result is a plan object hash
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
$self->logout;
# Result is list of components for the given test plan
return $result;
ThrowUserError('invalid-test-id-non-existent', {type => 'Product', id => $plan_id}) unless $plan;
ThrowUserError('testopia-permission-denied', {'object' => $plan}) unless $plan->canview;
# Result is list of test cases for the given test plan
return $plan->product;
}
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;
}
sub lookup_type_name_by_id
{
sub lookup_type_name_by_id {
my $self =shift;
my ($id) = @_;
$self->login;
Bugzilla->login(LOGIN_REQUIRED);
my $test_plan = new Bugzilla::Testopia::TestPlan({});
my $result = $test_plan->lookup_type($id);
$self->logout;
# Result is test plan type name for the given test plan type id
return $result;
return $test_plan->lookup_type($id);
}
sub lookup_type_id_by_name
{
sub lookup_type_id_by_name {
my $self =shift;
my ($name) = @_;
$self->login;
Bugzilla->login(LOGIN_REQUIRED);
my $test_plan = new Bugzilla::Testopia::TestPlan({});
my $result = $test_plan->lookup_type_by_name($name);
$self->logout;
if (!defined $result)
{
$result = 0;
};
# Result is test plan type id for the given test plan type name
return $result;
return $test_plan->lookup_type_by_name($name);
}
sub add_tag
{
my $self =shift;
my ($test_plan_id, $tag_name) = @_;
sub add_tag {
my $self = shift;
my ($plan_ids, $tags) = @_;
$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";
Bugzilla->login(LOGIN_REQUIRED);
my @ids = Bugzilla::Testopia::Util::process_list($plan_ids);
my @results;
foreach my $id (@ids){
my $plan = new Bugzilla::Testopia::TestPlan($id);
unless ($plan){
push @results, {FAILED => 1, message => "TestPlan $id does not exist"};
next;
}
unless ($plan->canedit){
push @results, {FAILED => 1, message => "You do not have rights to edit this test plan"};
next;
}
eval {
$plan->add_tag($tags);
}
if ($@){
push @results, {FAILED => 1, message => $@};
}
}
if (not $test_plan->canedit)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_plan->add_tag($tag_name);
if ($result == 1)
{
$self->logout;
die "Tag, " . $tag_name . ", already exists for Testplan, " . $test_plan_id;
}
$self->logout;
# Result 0 on success, otherwise an exception will be thrown
return $result;
# @results will be empty if successful
return @results;
}
sub remove_tag
{
my $self =shift;
my ($test_plan_id, $tag_name) = @_;
sub remove_tag {
my $self = shift;
my ($plan_id, $tag_name) = @_;
$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";
}
Bugzilla->login(LOGIN_REQUIRED);
if (not $test_plan->canedit)
{
$self->logout;
die "User Not Authorized";
}
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
my $test_tag = Bugzilla::Testopia::TestTag->check_tag($tag_name);
if (not defined $test_tag)
{
$self->logout;
die "Tag, " . $tag_name . ", does not exist";
}
my $result = $test_plan->remove_tag($test_tag->name);
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Plan', id => $plan_id}) unless $plan;
ThrowUserError('testopia-read-only', {'object' => $plan}) unless $plan->canedit;
$plan->remove_tag($tag_name);
$self->logout;
# Result 0 on success, otherwise an exception will be thrown
return 0;
}
sub get_tags
{
my $self =shift;
my ($test_plan_id) = @_;
sub get_tags {
my $self = shift;
my ($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";
}
Bugzilla->login(LOGIN_REQUIRED);
if (not $test_plan->canview)
{
$self->logout;
die "User Not Authorized";
}
my $plan = new Bugzilla::Testopia::TestPlan($plan_id);
my $result = $test_plan->tags;
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Plan', id => $plan_id}) unless $plan;
ThrowUserError('testopia-permission-denied', {'object' => $plan}) unless $plan->canview;
$self->logout;
# Result list of tags otherwise an exception will be thrown
return $result;
return $plan->tags;
}
1;
1;
__END__
=head1 NAME
Bugzilla::Testopia::Webservice::TestPlan
=head1 EXTENDS
Bugzilla::Webservice
=head1 DESCRIPTION
Provides methods for automated scripts to manipulate Testopia TestPlans
=head1 METHODS
=over
=item C<add_tag($plan_ids, $tags)>
Description: Add one or more tags to the selected test plans.
Params: $plan_ids - Integer/Array/String: An integer or alias representing the ID in the database,
an arry of plan_ids or aliases, or a string of comma separated plan_ids.
$tags - String/Array - A single tag, an array of tags,
or a comma separated list of tags.
Returns: undef/Array: undef on success or an array of hashes with failure
codes if a failure occured.
=item C<create($values)>
Description: Creates a new Test Plan object and stores it in the database.
Params: $values - Hash: A reference to a hash with keys and values
matching the fields of the test plan to be created.
Returns: The newly created object hash.
=item C<get($plan_id)>
Description: Used to load an existing test plan from the database.
Params: $id - Integer/String: An integer representing the ID in the database
for this plan.
Returns: A blessed Bugzilla::Testopia::TestPlan object hash
=item C<get_change_history($plan_id)>
Description: Get the list of changes to the fields of this plan.
Params: $plan_id - Integer/String: An integer representing the ID in the database
or a string representing the unique alias for this plan.
Returns: Array: An array of hashes with changed fields and their details.
=item C<get_tags($plan_id)>
Description: Get the list of tags attached to this plan.
Params: $plan_id - Integer/String: An integer representing the ID in the database
or a string representing the unique alias for this plan.
Returns: Array: An array of tag object hashes.
=item C<get_test_cases($plan_id)>
Description: Get the list of cases that this plan is linked to.
Params: $plan_id - Integer/String: An integer representing the ID in the database
for this plan.
Returns: Array: An array of test case object hashes.
=item C<get_test_runs($plan_id)>
Description: Get the list of runs in this plan.
Params: $plan_id - Integer/String: An integer representing the ID in the database
for this plan.
Returns: Array: An array of test run object hashes.
=item C<get_text($plan_id, $version)>
Description: The associated large text fields: Action, Expected Results, Setup, Breakdown
for a given version.
Params: $plan_id - Integer/String: An integer representing the ID in the database
or a string representing the unique alias for this plan.
$version - Integer: (OPTIONAL) The version of the text you want returned.
Defaults to the latest.
Returns: Hash: Text fields and values.
=item C<list($query)>
Description: Performs a search and returns the resulting list of test plans.
Params: $query - Hash: keys must match valid search fields.
+--------------------------------------------------------+
| Plan Search Parameters |
+--------------------------------------------------------+
| Key | Valid Values |
| author | A bugzilla login (email address) |
| author_type | (select from email_variants) |
| plan_id | comma separated integers |
| plan_text | String |
| plan_text_type | (select from query_variants) |
| plan_type | String: Product Name |
| product | String: Product Name |
| product_id | Integer |
| tags | String |
| tags_type | (select from tag_variants) |
| type_id | Integer |
| version | String: Product version |
+--------------------------------------------------------+
+--------------------------------------------------------+
| Paging and Sorting |
+--------------------------------------------------------+
| Key | Description |
| dir | "ASC" or "DESC" |
| order | field to sort by |
+--------------------------------------------------------+
| page_size | integer: how many per page |
| page | integer: page number |
| +++++++ OR +++++++ |
| start | integer: Start with which record |
| limit | integer: limit to how many |
+--------------------------------------------------------+
| viewall | 1: returns all records 0: first 25 |
+--------------------------------------------------------+
+----------------------------------------------------+
| query_variants |
+----------------+-----------------------------------+
| Key | Description |
| allwordssubstr | contains all of the words/strings |
| anywordssubstr | contains any of the words/strings |
| substring | contains the string |
| casesubstring | contains the string (exact case) |
| allwords | contains all of the words |
| anywords | contains any of the words |
| regexp | matches the regexp |
| notregexp | doesn't match the regexp |
+----------------+-----------------------------------+
+-------------------------------------+
| email_variants |
+--------------+----------------------+
| Key | Description |
| substring | contains |
| exact | is |
| regexp | matches regexp |
| notregexp | doesn't match regexp |
+--------------+----------------------+
+----------------------------------------------------+
| tag_variants |
+----------------+-----------------------------------+
| Key | Description |
| anyexact | is tagged with |
| allwordssubstr | contains all of the words/strings |
| anywordssubstr | contains any of the words/strings |
| substring | contains the string |
| casesubstring | contains the string (exact case) |
| regexp | matches the regexp |
| notregexp | doesn't match the regexp |
| allwords | contains all of the words |
| anywords | contains any of the words |
| nowords | contains none of the words |
+----------------------------------------------------+
Returns: Array: Matching test plans are retuned in a list of hashes.
=item C<lookup_type_id_by_name>
Params: $name - String: the status name.
Returns: Integer: ID of the plan type.
=item C<lookup_type_name_by_id>
Params: $id - Integer: ID of the plan stype to return
Returns: String: the type name.
=item C<remove_tag($plan_id, $tag)>
Description: Remove a tag from a plan.
Params: $plan_id - Integer/String: An integer or alias representing the ID in the database.
$tag - String - A single tag to be removed.
Returns: 0 on success.
=item C<update($ids, $values)>
Description: Updates the fields of the selected test plan.
Params: $ids - Integer: A single TestPlan ID.
$values - Hash of keys matching TestPlan fields and the new values
to set each field to.
Returns: Hash: The updated test plan object.
=back
=head1 SEE ALSO
=over
L<Bugzilla::Testopia::TestPlan>
L<Bugzilla::Webservice>
=back
=head1 AUTHOR
Greg Hendricks <ghendricks@novell.com>

View File

@@ -10,10 +10,14 @@
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
# The Original Code is the Bugzilla Testopia System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
# Dallas Harken <dharken@novell.com>
# The Initial Developer of the Original Code is Greg Hendricks.
# Portions created by Greg Hendricks are Copyright (C) 2006
# Novell. All Rights Reserved.
#
# Contributor(s): Dallas Harken <dharken@novell.com>
# Greg Hendricks <ghendricks@novell.com>
package Bugzilla::WebService::Testopia::TestRun;
@@ -21,6 +25,7 @@ use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::Constants;
use Bugzilla::Product;
use Bugzilla::User;
use Bugzilla::Testopia::TestRun;
@@ -28,338 +33,462 @@ use Bugzilla::Testopia::Search;
use Bugzilla::Testopia::Table;
# Utility method called by the list method
sub _list
{
sub get {
my $self = shift;
my ($run_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
# Result is a run object hash
my $run = new Bugzilla::Testopia::TestRun($run_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Build', id => $run_id}) unless $run;
ThrowUserError('testopia-permission-denied', {'object' => $run}) unless $run->canview;
$run->test_run_count();
$run->test_case_count();
return $run;
}
sub list {
my $self = shift;
my ($query) = @_;
Bugzilla->login(LOGIN_REQUIRED);
my $cgi = Bugzilla->cgi;
$cgi->param("current_tab", "run");
foreach (keys(%$query))
{
foreach (keys(%$query)){
$cgi->param($_, $$query{$_});
}
my $search = Bugzilla::Testopia::Search->new($cgi);
# Result is an array of test run hash maps
return Bugzilla::Testopia::Table->new('run',
'tr_xmlrpc.cgi',
$cgi,
undef,
$search->query()
)->list();
return Bugzilla::Testopia::Table->new('run','tr_xmlrpc.cgi',$cgi,undef,$search->query())->list();
}
sub get
{
my $self = shift;
my ($test_run_id) = @_;
$self->login;
#Result is a test run hash map
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";
}
$self->logout;
return $test_run;
}
sub list
{
my $self = shift;
my ($query) = @_;
$self->login;
my $list = _list($query);
$self->logout;
return $list;
}
sub create
{
sub create {
my $self =shift;
my ($new_values) = @_;
$self->login;
Bugzilla->login(LOGIN_REQUIRED);
my $product = Bugzilla::Testopia::Product->new($new_values->{'product_id'});
ThrowUserError('testopia-read-only', {'object' => $product}) unless $product->canedit;
my $test_run = Bugzilla::Testopia::TestRun->create($new_values);
my $run = Bugzilla::Testopia::TestRun->create($new_values);
$self->logout;
return $test_run->id;
return $run;
}
sub update
{
sub update {
my $self =shift;
my ($test_run_id, $new_values) = @_;
my ($run_id, $new_values) = @_;
$self->login;
Bugzilla->login(LOGIN_REQUIRED);
my $test_run = new Bugzilla::Testopia::TestRun($test_run_id);
if (not defined $test_run)
{
$self->logout;
die "Testrun, " . $test_run_id . ", not found";
}
my $run = new Bugzilla::Testopia::TestRun($run_id);
if (not $test_run->canedit)
{
$self->logout;
die "User Not Authorized";
}
$test_run->set_environment($new_values->{'environment_id'});
$test_run->set_build($new_values->{'build_id'});
$test_run->set_summary($new_values->{'summary'});
$test_run->set_manager($new_values->{'manager_id'});
$test_run->set_plan_text_version($new_values->{'plan_text_version'});
$test_run->set_notes($new_values->{'notes'});
$test_run->set_product_version($new_values->{'product_version'});
$test_run->update();
$self->logout;
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Run', id => $run_id}) unless $run;
ThrowUserError('testopia-read-only', {'object' => $run}) unless $run->canedit;
my $timestamp;
$timestamp = $run->stop_date;
$timestamp = undef if $new_values->{'status'};
$timestamp = get_time_stamp() if $new_values->{'status'} == 0 && !$run->stop_date;
$run->set_summary(trim($new_values->{'summary'})) if exists $new_values->{'summary'};
$run->set_product_version($new_values->{'product_version')) if $new_values->{'product_version'};
$run->set_plan_text_version($new_values->{'plan_text_version')) if $new_values->{'plan_text_version'};
$run->set_build($new_values->{'build_id')) if $new_values->{'build_id'};
$run->set_environment($new_values->{'environment_id')) if $new_values->{'environment_id'};
$run->set_manager($new_values->{'manager_id')) if $new_values->{'manager_id'};
$run->set_notes($new_values->{'notes')} if exists $cgi->{'notes'};
$run->set_stop_date($timestamp) if $new_values->{'status'};
# Result is modified test run on success, otherwise an exception will be thrown
return $test_run;
$run->update();
# Result is modified test run, otherwise an exception will be thrown
return $run;
}
sub get_test_cases
{
my $self =shift;
my ($test_run_id) = @_;
sub get_change_history {
my $self = shift;
my ($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";
}
Bugzilla->login(LOGIN_REQUIRED);
if (not $test_run->canview)
{
$self->logout;
die "User Not Authorized";
}
my $result = $test_run->cases();
my $run = new Bugzilla::Testopia::TestRun($run_id);
$self->logout;
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Run', id => $run_id}) unless $run;
ThrowUserError('testopia-permission-denied', {'object' => $run}) unless $run->canview;
# Result list of changes otherwise an exception will be thrown
return $run->history;
}
sub get_test_cases {
my $self = shift;
my ($run_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
# Result is a run object hash
my $run = new Bugzilla::Testopia::TestRun($run_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Build', id => $run_id}) unless $run;
ThrowUserError('testopia-permission-denied', {'object' => $run}) unless $run->canview;
# Result is list of test cases for the given test run
return $result;
return $run->cases;
}
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";
}
sub get_test_case_runs {
my $self = shift;
my ($run_id, $current) = @_;
if (not $test_run->canview)
{
$self->logout;
die "User Not Authorized";
}
Bugzilla->login(LOGIN_REQUIRED);
my $result = $test_run->caseruns();
# Result is a run object hash
my $run = new Bugzilla::Testopia::TestRun($run_id);
$self->logout;
# Result is list of test case runs for the given test run
return $result;
ThrowUserError('invalid-test-id-non-existent', {type => 'Build', id => $run_id}) unless $run;
ThrowUserError('testopia-permission-denied', {'object' => $run}) unless $run->canview;
# Result is list of test cases for the given test run
return $run->current_caseruns if $current;
return $run->caseruns;
}
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";
}
sub get_test_plan {
my $self = shift;
my ($run_id) = @_;
if (not $test_run->canview)
{
$self->logout;
die "User Not Authorized";
}
Bugzilla->login(LOGIN_REQUIRED);
my $result = $test_run->plan();
# Result is a run object hash
my $run = new Bugzilla::Testopia::TestRun($run_id);
$self->logout;
# Result is test plan for the given test run
return $result;
ThrowUserError('invalid-test-id-non-existent', {type => 'Build', id => $run_id}) unless $run;
ThrowUserError('testopia-permission-denied', {'object' => $run}) unless $run->canview;
# Result is list of test cases for the given test run
return $run->plan;
}
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_id_by_name {
return { FAILED => 1, message => 'This method is considered harmful and has been depricated. Please use Environment::check_environment instead'};
}
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;
sub lookup_environment_name_by_id {
return { FAILED => 1, message => 'This method is considered harmful and has been depricated. Please use Environment::get instead'};
}
sub add_tag
{
my $self =shift;
my ($test_run_id, $tag_name) = @_;
sub add_tag {
my $self = shift;
my ($run_ids, $tags) = @_;
$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";
Bugzilla->login(LOGIN_REQUIRED);
my @ids = Bugzilla::Testopia::Util::process_list($run_ids);
my @results;
foreach my $id (@ids){
my $run = new Bugzilla::Testopia::TestRun($id);
unless ($run){
push @results, {FAILED => 1, message => "TestRun $id does not exist"};
next;
}
unless ($run->canedit){
push @results, {FAILED => 1, message => "You do not have rights to edit this test run"};
next;
}
eval {
$run->add_tag($tags);
}
if ($@){
push @results, {FAILED => 1, message => $@};
}
}
if (not $test_run->canedit)
{
$self->logout;
die "User Not Authorized";
}
$test_run->add_tag($tag_name);
# @results will be empty if successful
return @results;
}
$self->logout;
sub remove_tag {
my $self = shift;
my ($run_id, $tag_name) = @_;
Bugzilla->login(LOGIN_REQUIRED);
my $run = new Bugzilla::Testopia::TestRun($run_id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Run', id => $run_id}) unless $run;
ThrowUserError('testopia-read-only', {'object' => $run}) unless $run->canedit;
$run->remove_tag($tag_name);
# Result 0 on success, otherwise an exception will be thrown
return 0;
}
sub remove_tag
{
my $self =shift;
my ($test_run_id, $tag_name) = @_;
sub get_tags {
my $self = shift;
my ($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";
}
Bugzilla->login(LOGIN_REQUIRED);
if (not $test_run->canedit)
{
$self->logout;
die "User Not Authorized";
}
my $run = new Bugzilla::Testopia::TestRun($run_id);
my $test_tag = Bugzilla::Testopia::TestTag->check_tag($tag_name);
if (not defined $test_tag)
{
$self->logout;
die "Tag, " . $tag_name . ", does not exist";
}
my $result = $test_run->remove_tag($test_tag->name);
ThrowUserError('invalid-test-id-non-existent', {type => 'Test Run', id => $run_id}) unless $run;
ThrowUserError('testopia-permission-denied', {'object' => $run}) unless $run->canview;
$self->logout;
# Result 0 on success, otherwise an exception will be thrown
return 0;
}
sub get_tags
{
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->tags;
$self->logout;
# Result list of tags otherwise an exception will be thrown
return $result;
return $run->tags;
}
1;
1;
__END__
=head1 NAME
Bugzilla::Testopia::Webservice::TestRun
=head1 EXTENDS
Bugzilla::Webservice
=head1 DESCRIPTION
Provides methods for automated scripts to manipulate Testopia TestRuns
=head1 METHODS
=over
=item C<add_tag($run_ids, $tags)>
Description: Add one or more tags to the selected test runs.
Params: $run_ids - Integer/Array/String: An integer or alias representing the ID in the database,
an arry of run_ids or aliases, or a string of comma separated run_ids.
$tags - String/Array - A single tag, an array of tags,
or a comma separated list of tags.
Returns: undef/Array: undef on success or an array of hashes with failure
codes if a failure occured.
=item C<create($values)>
Description: Creates a new Test Run object and stores it in the database.
Params: $values - Hash: A reference to a hash with keys and values
matching the fields of the test run to be created.
Returns: The newly created object hash.
=item C<get($run_id)>
Description: Used to load an existing test run from the database.
Params: $id - Integer/String: An integer representing the ID in the database
for this run.
Returns: A blessed Bugzilla::Testopia::TestRun object hash
=item C<get_change_history($run_id)>
Description: Get the list of changes to the fields of this run.
Params: $run_id - Integer/String: An integer representing the ID in the database
or a string representing the unique alias for this run.
Returns: Array: An array of hashes with changed fields and their details.
=item C<get_tags($run_id)>
Description: Get the list of tags attached to this run.
Params: $run_id - Integer/String: An integer representing the ID in the database
or a string representing the unique alias for this run.
Returns: Array: An array of tag object hashes.
=item C<get_test_case_runs($run_id, $current)>
Description: Get the list of cases that this run is linked to.
Params: $run_id - Integer/String: An integer representing the ID in the database
for this run.
$current - Boolean: 1 to only include the current set (what is displayed
in the web page) 0: to return all, current and historical.
Returns: Array: An array of test case object hashes.
=item C<get_test_cases($run_id)>
Description: Get the list of cases that this run is linked to.
Params: $run_id - Integer/String: An integer representing the ID in the database
for this run.
Returns: Array: An array of test case object hashes.
=item C<get_test_plan($run_id)>
Description: Get the plan that this run is associated with.
Params: $run_id - Integer/String: An integer representing the ID in the database
for this run.
Returns: Hash: A plan object hash.
=item C<list($query)>
Description: Performs a search and returns the resulting list of test runs.
Params: $query - Hash: keys must match valid search fields.
build A fine Build indeed
ctype json
current_tab run
environment 1183153988 PerlUnit Test for Testopia API -- Environment.create -- PLEASE IGNORE
limit 25
manager
manager_type substring
milestone 3.0
notes
notes_type allwordssubstr
plan_id
product_id 2
run_id
run_status 0
summary
summary_type allwordssubstr
tags
tags_type anyexact
version 2.20
+--------------------------------------------------------+
| Run Search Parameters |
+--------------------------------------------------------+
| Key | Valid Values |
| build | String: Product Name |
| build_id | Integer |
| environment | String: Product Name |
| environment_id | Integer |
| manager | A bugzilla login (email address) |
| manager_type | (select from email_variants) |
| milestone | String |
| notes | String |
| notes_type | (select from query_variants) |
| plan_id | comma separated integers |
| product | String: Product Name |
| product_id | Integer |
| run_id | comma separated integers |
| run_status | 1: RUNNING 0: STOPPED |
| summary | String |
| summary_type | (select from query_variants) |
| tags | String |
| tags_type | (select from tag_variants) |
| type_id | Integer |
| version | String: Product version |
+--------------------------------------------------------+
+--------------------------------------------------------+
| Paging and Sorting |
+--------------------------------------------------------+
| Key | Description |
| dir | "ASC" or "DESC" |
| order | field to sort by |
+--------------------------------------------------------+
| page_size | integer: how many per page |
| page | integer: page number |
| +++++++ OR +++++++ |
| start | integer: Start with which record |
| limit | integer: limit to how many |
+--------------------------------------------------------+
| viewall | 1: returns all records 0: first 25 |
+--------------------------------------------------------+
+----------------------------------------------------+
| query_variants |
+----------------+-----------------------------------+
| Key | Description |
| allwordssubstr | contains all of the words/strings |
| anywordssubstr | contains any of the words/strings |
| substring | contains the string |
| casesubstring | contains the string (exact case) |
| allwords | contains all of the words |
| anywords | contains any of the words |
| regexp | matches the regexp |
| notregexp | doesn't match the regexp |
+----------------+-----------------------------------+
+-------------------------------------+
| email_variants |
+--------------+----------------------+
| Key | Description |
| substring | contains |
| exact | is |
| regexp | matches regexp |
| notregexp | doesn't match regexp |
+--------------+----------------------+
+----------------------------------------------------+
| tag_variants |
+----------------+-----------------------------------+
| Key | Description |
| anyexact | is tagged with |
| allwordssubstr | contains all of the words/strings |
| anywordssubstr | contains any of the words/strings |
| substring | contains the string |
| casesubstring | contains the string (exact case) |
| regexp | matches the regexp |
| notregexp | doesn't match the regexp |
| allwords | contains all of the words |
| anywords | contains any of the words |
| nowords | contains none of the words |
+----------------------------------------------------+
Returns: Array: Matching test runs are retuned in a list of hashes.
=item C<remove_tag($run_id, $tag)>
Description: Remove a tag from a run.
Params: $run_id - Integer/String: An integer or alias representing the ID in the database.
$tag - String - A single tag to be removed.
Returns: 0 on success.
=item C<update($ids, $values)>
Description: Updates the fields of the selected test run.
Params: $ids - Integer: A single TestRun ID.
$values - Hash of keys matching TestRun fields and the new values
to set each field to.
Returns: Hash: The updated test run object.
=back
=head1 SEE ALSO
=over
L<Bugzilla::Testopia::TestRun>
L<Bugzilla::Webservice>
=back
=head1 AUTHOR
Greg Hendricks <ghendricks@novell.com>

View File

@@ -52,9 +52,9 @@ my $action = $cgi->param('action') || '';
if ($cgi->param('caserun_id')){
$caserun = Bugzilla::Testopia::TestCaseRun->new($cgi->param('caserun_id'));
}
elsif ($cgi->param('case_id')){
$caserun = Bugzilla::Testopia::TestCaseRun->new($cgi->param('case_id'),
$cgi->param('run_id'),
elsif ($cgi->param('run_id')){
$caserun = Bugzilla::Testopia::TestCaseRun->new($cgi->param('run_id'),
$cgi->param('case_id'),
$cgi->param('build_id'),
$cgi->param('env_id'));
}