Wrote some API tests

Hello.
Against 3.3.HEAD
Adds 178 tests

26 tests fails
It’s the same bug that I can add two different CF values for one ticket
even if ticket has type SelectSingle.
Best regards. Ruslan.

09record_customfields.t.patch (6.36 KB)

Hello,

we use RT 3.2.2 and meet big troubles with custom action scrips - it works
only sometimes (maybe just only once). This example for is i.e. not
working well if used in Scrip for specific Queue.
Is this approach wrong/where is the problem?
I (customer) doesn’t want to use additional files like yours good one
Action/NotifyGroup.pm, because the LoadedGroup will change depending on
some ticket info (Customer CustomFields)…

Prepare part:
----- cut here -----
package RT::Action::tmp;
use strict;
use vars qw/@ISA/;
require RT::Action::Notify;
@ISA = qw(RT::Action::Notify);
sub SetRecipients {
my $self = shift;

my ($group);
my @Bcc;

$group = new RT::Group($RT::SystemUser);
$group->LoadUserDefinedGroup("RT AdminCc");

unless ($group->Id ) {
    $RT::Logger->warning("Searching Group Global AdminCc failed, can't set recipients!\n");

    return;
}

my $members = $group->UserMembersObj();
while (my $member = $members->Next()) {

    my $user = $member->EmailAddress;
    if ($user && ! ( grep (/^$user$/, @Bcc) ) ) {
            push ( @Bcc, $user );
    }
}

if ($RT::UseFriendlyToLine) {
        push (
            @{$self->{'PseudoTo'}},
            sprintf($RT::FriendlyToLineFormat, "GroupNotify", $self->TicketObj->id),
        );
}

if ($RT::NotifyActor) {
    # Do not send notification to the crator of the transaction
    my $creator;
    $creator = $self->TransactionObj->CreatorObj->EmailAddress() if ($self->TransactionObj);
    # override possible 'Bcc'

    @{$self->{'Bcc'}} = grep (!/^$creator$/, @Bcc);
} else {
    @{$self->{'Bcc'}} = @Bcc;    }

$RT::Logger->warning("GroupNotify Bcc is:".join(',',@{$self->{'Bcc'}})."\n");

return (1)

}

1;

my $tmpscrip;
$tmpscrip = new RT::Action::tmp(
TransactionObj => $self->{‘TransactionObj’},
TemplateObj => $self->{‘TemplateObj’},
TicketObj => $self->{‘TicketObj’},
ScripObj => $self->{‘ScripObj’},
Type => $self->{‘Type’},
CurrentUser => $self->CurrentUser,
);

$self->{‘tmpscrip’} = $tmpscrip;

my $res=$tmpscrip->Prepare();
#use Data::Dumper;
#$RT::Logger->warning(Dumper($self->TemplateObj->MIMEObj->head));
return $res;
----- cut here -----
Commit part is only:
----- cut here -----
$self->{‘tmpscrip’}->Commit;
----- cut here -----

Jan Okrouhlďż˝

//--------------------------------------±----okrouhly@civ.zcu.cz-\
|Laboratory for Computer Science | phone: +420 377 632 837 |
|University of West Bohemia | location: Univerzitni 22 |
|Americka 42, 306 14 Pilsen, Czech Republic| room: UI402 |
±--------------------------------------73-!-de-OK1INC@OK0PPL.#BOH.CZE.EU+
| Monday or Tuesday: | phone: +420 224 355 263 |
\_____________CESNET z.s.p.o.|location: Zikova 4, Prague//

Hello,

we use RT 3.2.2 and meet big troubles with custom action scrips - it works
only sometimes (maybe just only once). This example for is i.e. not
working well if used in Scrip for specific Queue.
Is this approach wrong/where is the problem?
I (customer) doesn’t want to use additional files like yours good one
Action/NotifyGroup.pm, because the LoadedGroup will change depending on
some ticket info (Customer CustomFields)…

Prepare part:

You’re confusing Scrips with Scripts. All of that belongs in a perl
script, not in an RT Scrip.

Here’s an example of how I add a Cc in a scrip.

Description: AddWatcherCompanyX
Condition: User Defined

Custom condition:
return undef unless ($self->TransactionObj->Type eq “Create”);
return undef if ($self->TicketObj->FirstCustomFieldValue(‘TicketMail’)
=~ /Internal/i);
return undef unless ($self->TicketObj->FirstCustomFieldValue(‘Domain’) =~
/CompanyX/i);
return 1;

Action: User Defined
Custom action preparation code:
my ($status, $msg) = $self->TicketObj->AddWatcher(Type => ‘Cc’, Email
=> “suscom-outage@gwi.net” );
return 1;

Custom action cleanup code:
return 1;
Stage: TransactionCreate
Template: Global template: Blank

Andy Harrison

Hello,

we use RT 3.2.2 and meet big troubles with custom action scrips - it works
only sometimes (maybe just only once). This example for is i.e. not
working well if used in Scrip for specific Queue.
Is this approach wrong/where is the problem?
I (customer) doesn’t want to use additional files like yours good one
Action/NotifyGroup.pm, because the LoadedGroup will change depending on
some ticket info (Customer CustomFields)…

Prepare part:

You’re confusing Scrips with Scripts. All of that belongs in a perl
script, not in an RT Scrip.

But I do not want to add a Cc Watcher, I just want to send a specific
message (defined by Template) to specific “group” of recipients (nor Ccs
nor AdminCcs).

Here’s an example of how I add a Cc in a scrip.

Description: AddWatcherCompanyX
Condition: User Defined

Custom condition:
return undef unless ($self->TransactionObj->Type eq “Create”);
return undef if ($self->TicketObj->FirstCustomFieldValue(‘TicketMail’)
=~ /Internal/i);
return undef unless ($self->TicketObj->FirstCustomFieldValue(‘Domain’) =~
/CompanyX/i);
return 1;

Action: User Defined
Custom action preparation code:
my ($status, $msg) = $self->TicketObj->AddWatcher(Type => ‘Cc’, Email
=> “suscom-outage@gwi.net” );
return 1;

Custom action cleanup code:
return 1;
Stage: TransactionCreate
Template: Global template: Blank


Andy Harrison

Jan Okrouhlďż˝

//--------------------------------------+---–okrouhly@civ.zcu.cz-\
|Laboratory for Computer Science | phone: +420 377 632 837 |
|University of West Bohemia | location: Univerzitni 22 |
|Americka 42, 306 14 Pilsen, Czech Republic| room: UI402 |
±--------------------------------------73-!-de-OK1INC@OK0PPL.#BOH.CZE.EU+
| Monday or Tuesday: | phone: +420 224 355 263 |
\_____________CESNET z.s.p.o.|location: Zikova 4, Prague//

Jan Okrouhly wrote:

Hello,

we use RT 3.2.2 and meet big troubles with custom action scrips - it works
only sometimes (maybe just only once). This example for is i.e. not
working well if used in Scrip for specific Queue.
Is this approach wrong/where is the problem?
I (customer) doesn’t want to use additional files like yours good one
Action/NotifyGroup.pm, because the LoadedGroup will change depending on
some ticket info (Customer CustomFields)…
Start from Request Tracker Wiki
Comments about code below.

Prepare part:
----- cut here -----
package RT::Action::tmp;
use strict;
use vars qw/@ISA/;
require RT::Action::Notify;
@ISA = qw(RT::Action::Notify);
sub SetRecipients {
my $self = shift;

my ($group);
my @Bcc;

$group = new RT::Group($RT::SystemUser);
$group->LoadUserDefinedGroup("RT AdminCc");

unless ($group->Id ) {
    $RT::Logger->warning("Searching Group Global AdminCc failed, can't set recipients!\n");

    return;
}

my $members = $group->UserMembersObj();
while (my $member = $members->Next()) {

    my $user = $member->EmailAddress;
    if ($user && ! ( grep (/^$user$/, @Bcc) ) ) {
      if ($user && ! ( grep (/^\Q$user\E$/, @Bcc) ) ) {
            push ( @Bcc, $user );
    }
}

if ($RT::UseFriendlyToLine) {
        push (
            @{$self->{'PseudoTo'}},
            sprintf($RT::FriendlyToLineFormat, "GroupNotify", $self->TicketObj->id),
        );
}

if ($RT::NotifyActor) {

unless($RT::NotifyActor) {

    # Do not send notification to the crator of the transaction
    my $creator;
    $creator = $self->TransactionObj->CreatorObj->EmailAddress() if ($self->TransactionObj);
    # override possible 'Bcc'

    @{$self->{'Bcc'}} = grep (!/^$creator$/, @Bcc);
      @{$self->{'Bcc'}} = grep (!/^\Q$creator\E$/, @Bcc);

But I do not want to add a Cc Watcher, I just want to send a specific
message (defined by Template) to specific “group” of recipients (nor Ccs
nor AdminCcs).

It was intended to be more of an example of what a scrip will look like.

But how would you determine the group to use? The requestor’s group?
The current user? The current queue (i.e. who has rights to it)?

Andy Harrison

Jan Okrouhly wrote:

Hello,

we use RT 3.2.2 and meet big troubles with custom action scrips - it works
only sometimes (maybe just only once). This example for is i.e. not
working well if used in Scrip for specific Queue.
Is this approach wrong/where is the problem?
I (customer) doesn’t want to use additional files like yours good one
Action/NotifyGroup.pm, because the LoadedGroup will change depending on
some ticket info (Customer CustomFields)…
Start from Request Tracker Wiki

I used to debug it, but it there had to be some BIG mistake in usage of
objects or classes, RT 3.2.2, or Perl 5.8.4 used…

The simple code bellow works sometimes ones, sometimes no. It is not
deterministic - that’s the PROBLEM.

Comments about code below.

Thank You for comments, but PLEASE try this code:
package RT::Action::tmp;
use strict;
use base qw(RT::Action::Notify);

sub SetRecipients {
my $self = shift;

@{$self->{'Bcc'}} = ('somebody@test.it.com');
return 1

}

1;

my $tmpscrip;
$tmpscrip = new RT::Action::tmp(
TransactionObj => $self->{‘TransactionObj’},
TemplateObj => $self->{‘TemplateObj’},
TicketObj => $self->{‘TicketObj’},
ScripObj => $self->{‘ScripObj’},
Type => $self->{‘Type’},
CurrentUser => $self->CurrentUser,
);

$self->{‘tmpscrip’} = $tmpscrip;

my $res=$tmpscrip->Prepare();
use Data::Dumper;
$RT::Logger->warning(“Res=”.$res.Dumper($self->TemplateObj->MIMEObj->head));
return $res;

Prepare part:
----- cut here -----
package RT::Action::tmp;
use strict;
use vars qw/@ISA/;
require RT::Action::Notify;
@ISA = qw(RT::Action::Notify);
sub SetRecipients {
my $self = shift;

my ($group);
my @Bcc;

$group = new RT::Group($RT::SystemUser);
$group->LoadUserDefinedGroup("RT AdminCc");

unless ($group->Id ) {
    $RT::Logger->warning("Searching Group Global AdminCc failed, can't set recipients!\n");

    return;
}

my $members = $group->UserMembersObj();
while (my $member = $members->Next()) {

    my $user = $member->EmailAddress;
    if ($user && ! ( grep (/^$user$/, @Bcc) ) ) {
      if ($user && ! ( grep (/^\Q$user\E$/, @Bcc) ) ) {
            push ( @Bcc, $user );
    }
}

if ($RT::UseFriendlyToLine) {
        push (
            @{$self->{'PseudoTo'}},
            sprintf($RT::FriendlyToLineFormat, "GroupNotify", $self->TicketObj->id),
        );
}

if ($RT::NotifyActor) {

unless($RT::NotifyActor) {

    # Do not send notification to the crator of the transaction
    my $creator;
    $creator = $self->TransactionObj->CreatorObj->EmailAddress() if ($self->TransactionObj);
    # override possible 'Bcc'

    @{$self->{'Bcc'}} = grep (!/^$creator$/, @Bcc);
      @{$self->{'Bcc'}} = grep (!/^\Q$creator\E$/, @Bcc);
} else {
    @{$self->{'Bcc'}} = @Bcc;    }

$RT::Logger->warning("GroupNotify Bcc is:".join(',',@{$self->{'Bcc'}})."\n");

return (1)

}

1;

my $tmpscrip;
$tmpscrip = new RT::Action::tmp(
TransactionObj => $self->{‘TransactionObj’},
TemplateObj => $self->{‘TemplateObj’},
TicketObj => $self->{‘TicketObj’},
ScripObj => $self->{‘ScripObj’},
Type => $self->{‘Type’},
CurrentUser => $self->CurrentUser,
);

$self->{‘tmpscrip’} = $tmpscrip;

my $res=$tmpscrip->Prepare();
#use Data::Dumper;
#$RT::Logger->warning(Dumper($self->TemplateObj->MIMEObj->head));
return $res;
----- cut here -----
Commit part is only:
----- cut here -----
$self->{‘tmpscrip’}->Commit;
----- cut here -----

Jan Okrouhlďż˝

//--------------------------------------+---–okrouhly@civ.zcu.cz-\
|Laboratory for Computer Science | phone: +420 377 632 837 |
|University of West Bohemia | location: Univerzitni 22 |
|Americka 42, 306 14 Pilsen, Czech Republic| room: UI402 |
±--------------------------------------73-!-de-OK1INC@OK0PPL.#BOH.CZE.EU+
| Monday or Tuesday: | phone: +420 224 355 263 |
\_____________CESNET z.s.p.o.|location: Zikova 4, Prague//

Jan Okrouhlďż˝

//--------------------------------------+---–okrouhly@civ.zcu.cz-\
|Laboratory for Computer Science | phone: +420 377 632 837 |
|University of West Bohemia | location: Univerzitni 22 |
|Americka 42, 306 14 Pilsen, Czech Republic| room: UI402 |
±--------------------------------------73-!-de-OK1INC@OK0PPL.#BOH.CZE.EU+
| Monday or Tuesday: | phone: +420 224 355 263 |
\_____________CESNET z.s.p.o.|location: Zikova 4, Prague//

Jan Okrouhly wrote:

Jan Okrouhly wrote:

Hello,

we use RT 3.2.2 and meet big troubles with custom action scrips - it works
only sometimes (maybe just only once). This example for is i.e. not
working well if used in Scrip for specific Queue.
Is this approach wrong/where is the problem?
I (customer) doesn’t want to use additional files like yours good one
Action/NotifyGroup.pm, because the LoadedGroup will change depending on
some ticket info (Customer CustomFields)…

Start from Request Tracker Wiki

I used to debug it, but it there had to be some BIG mistake in usage of
objects or classes, RT 3.2.2, or Perl 5.8.4 used…

The simple code bellow works sometimes ones, sometimes no. It is not
deterministic - that’s the PROBLEM.
In most cases it’s really your problem if something sometimes works and
sometimes not. You should run apache in -X mode in such case to be
shure. Read Request Tracker Wiki.

Try to use next code in the commit phase:

(delete $self->{‘tmpscrip’})->Commit;

PS: IMHO it’s first time when somebody tries to put action package into
custom action code :slight_smile:

Hello.
Against 3.3.HEAD
Adds 178 tests

26 tests fails

More than that fail when it’s run as part of the test suite, since it
includes some assumptions about the starting database. I’m working on
patching that first.

All tests now pass. (With the exception of the SKIP tests).

One was a bug in RT. The other was a bug in DBIx::SearchBuilder’s
alternate key caching. A new version of SB is now winging it’s way to
cpan.

-jOn Thu, Dec 09, 2004 at 04:58:55PM -0500, Jesse Vincent wrote:

It’s the same bug that I can add two different CF values for one ticket
even if ticket has type SelectSingle.
Best regards. Ruslan.


Rt-devel mailing list
Rt-devel@lists.bestpractical.com
The rt-devel Archives

Jesse Vincent wrote:

Hello.
Against 3.3.HEAD
Adds 178 tests

26 tests fails

More than that fail when it’s run as part of the test suite, since it
includes some assumptions about the starting database. I’m working on
patching that first.
I argue. It does include one assumption about DB: DB should be just
after ‘make initdb’. Jesse, I think if you want >90% test coverage then
test suit would be very big and it would be problem if one test file
would be rely on data inserted by other files. IMHO we should reinit DB
before each file. Yes, it would be slower, but allow to run this or that
test file only.

More than that fail when it’s run as part of the test suite, since it
includes some assumptions about the starting database. I’m working on
patching that first.
I argue. It does include one assumption about DB: DB should be just
after ‘make initdb’. Jesse, I think if you want >90% test coverage then
test suit would be very big and it would be problem if one test file
would be rely on data inserted by other files. IMHO we should reinit DB
before each file. Yes, it would be slower, but allow to run this or that
test file only.

I strongly disagree with that. A chunk of the test suite should be able
to run with either a clean database or the rest of the test suite
having been run. Which is now the case for the tests you wrote.

Jesse Vincent wrote:

More than that fail when it’s run as part of the test suite, since it
includes some assumptions about the starting database. I’m working on
patching that first.

I argue. It does include one assumption about DB: DB should be just
after ‘make initdb’. Jesse, I think if you want >90% test coverage then
test suit would be very big and it would be problem if one test file
would be rely on data inserted by other files. IMHO we should reinit DB
before each file. Yes, it would be slower, but allow to run this or that
test file only.

I strongly disagree with that. A chunk of the test suite should be able
to run with either a clean database or the rest of the test suite
having been run. Which is now the case for the tests you wrote.

So please show me how my test file can be rewriten to be independant
from other tests/DB data and check all the cases that it checks now.

It’s the pain to write tests and take on mind that DB can contain any
data. It would be pain to track why your new tests break some tests in
other files that runs after yours. Contributor can not even know how
tests in that files works.

Are you shure that you can always write tests that would be absolutely
independant from data in DB. I have great confidence that I can’t write
some tests if I’m not sure that DB in some well known state.

IMHO it’s also a reason why people doesn’t contribute test suites.

May be I don’t know something, but I don’t know how to run this or that
test file in current RT test suit. Next command I was using to run my
test file after each edition:
./configure --with-web-user=apache --with-web-group=apache
–with-devel-mode; sudo sh reinitdb_silent.sh; sudo perl
lib/t/09record_customfields.t
Is it normal for test case?

Next is normal:
make test TEST_FILES=lib/t/09record_customfields.t

SVK is an example. Add SKIP block to one test in the middle of file and
all subsequent tests in this file will fail.

May be we should open discussion on perl.qa?

If you help us write test cases easier in any way then at least I spend
more time to add more tests to RT API.

			Best regards. Ruslan.

PS: I must read more English literature to describe my philosophical
thoughts easier :confused:

So please show me how my test file can be rewriten to be independant
from other tests/DB data and check all the cases that it checks now.

The only assumption you were making that was harmful was that there
would be no global custom fields. So all I did was add a couple lines to
ensure thatif they’re there, they get deleted.

It’s the pain to write tests and take on mind that DB can contain any
data. It would be pain to track why your new tests break some tests in
other files that runs after yours. Contributor can not even know how
tests in that files works.

Are you shure that you can always write tests that would be absolutely
independant from data in DB. I have great confidence that I can’t write
some tests if I’m not sure that DB in some well known state.

I’ve not found it at all hard to test my assumptions about the database
state before running my tests as I write a test script.

May be I don’t know something, but I don’t know how to run this or that
test file in current RT test suit. Next command I was using to run my
test file after each edition:
./configure --with-web-user=apache --with-web-group=apache
–with-devel-mode; sudo sh reinitdb_silent.sh; sudo perl
lib/t/09record_customfields.t
Is it normal for test case?

Next is normal:
make test TEST_FILES=lib/t/09record_customfields.t

Yes. And I’d love to get there. RT uses autoconf, not MakeMaker, so we
don’t have all the makemaker magic at our fingertips. We spoke on IRC about
dding the support code to handle test files droppted into
lib/t/regression. I’d be thrilled if this could support cpan style tests
that can more easily stand alone.

If you help us write test cases easier in any way then at least I spend
more time to add more tests to RT API.

Thanks. It is much appreciated and I do want to make it happen. Once 3.4
gets out the door, I’d love to do work on this for the next release. I
suppose I could create a PLATANO (experimental) branch for testsuite
work.

Jesse

Jesse Vincent wrote:

So please show me how my test file can be rewriten to be independant
from other tests/DB data and check all the cases that it checks now.

The only assumption you were making that was harmful was that there
would be no global custom fields. So all I did was add a couple lines to
ensure thatif they’re there, they get deleted.
With this code you clean up DB to some known state, don’t you? So with
which idea you disagree? Do you want to write cleanup code for each test
file before it can be safely run independant from other tests? Idea that
“you don’t know state of the system” impel to make errors in tests.

It’s not complete test file. It should be ~x3 larger to cover all
things. Would it be enough to delete global CFs to make shure that all
works fine as you expect?

I’ve not found it at all hard to test my assumptions about the database
state before running my tests as I write a test script.
Do you want to think about this at all?

Ufff. I just don’t understand the reason? I don’t want to write cleanup
code in the beginning of the test files. I even don’t want to init data
in test case, I want run one command/sub/method/require that will reinit
DB to some predefined state. I don’t see any benifits in your approach.

I don’t know what to add. ruz shuts up.

But how would you determine the group to use? The requestor’s group?
The current user? The current queue (i.e. who has rights to it)?

Anyway.
As I’ve written in my case it was I CustomField set on Tickets
which Value identifie the Group name → Emails… This is not a core of
solved problem with my scrip codes.

Jan Okrouhlý

In that case, I see no reason you can’t use Ruslan’s NotifyGroup
module. Since you probably have a finite amount of possible values in
your custom field, you could create one scrip per value.

Use a custom condition:
# Create, or whatever condition.
return undef unless ($self->TransactionObj->Type eq “Create”);
return undef if ($self->TicketObj->FirstCustomFieldValue(‘Your
Custom Field Name’) =~ /Value you’re searching for/i);
return 1;

Choose the appropriate action generated by Ruslan’s NotifyGroup.
Template: TemplateForSomeValue1

Then in the Template, just specify your cc at the very top line of the
template (making sure to put an empty line after) and it should work.

Andy Harrison

But how would you determine the group to use? The requestor’s group?
The current user? The current queue (i.e. who has rights to it)?

Anyway.
As I’ve written in my case it was I CustomField set on Tickets
which Value identifie the Group name → Emails… This is not a core of
solved problem with my scrip codes.

Jan Okrouhlďż˝

Yes, here is one way how to do that:
use system scrip action Notify (with no Arguments) and then
put up code setting BCc,Cc either To to the very beginning of given
Template.

Ana another way is (I HOPE) to write custom action prepare code (inspired
in RT3.2.2 __Approvals’ scrips) like:
----- cut here ----

package RT::Action::tmp;
require RT::Action::Notify;
use strict;
use vars qw/@ISA/;
@ISA=qw(RT::Action::Notify);

sub SetRecipients {

Your Code preparing Bcc, To or whatever

@{$self->{‘Bcc’}}=(‘i.e. some needed addresses@st.worldcomain’);
}

bless($self, ‘RT::Action::tmp’);
return $self->Prepare;

— cut here —

In that case, I see no reason you can’t use Ruslan’s NotifyGroup
module. Since you probably have a finite amount of possible values in
your custom field, you could create one scrip per value.

Use a custom condition:
# Create, or whatever condition.
return undef unless ($self->TransactionObj->Type eq “Create”);
return undef if ($self->TicketObj->FirstCustomFieldValue(‘Your
Custom Field Name’) =~ /Value you’re searching for/i);
return 1;

Choose the appropriate action generated by Ruslan’s NotifyGroup.
Template: TemplateForSomeValue1

Then in the Template, just specify your cc at the very top line of the
template (making sure to put an empty line after) and it should work.


Andy Harrison

Jan Okrouhlďż˝

//--------------------------------------+---–okrouhly@civ.zcu.cz-\
|Laboratory for Computer Science | phone: +420 377 632 837 |
|University of West Bohemia | location: Univerzitni 22 |
|Americka 42, 306 14 Pilsen, Czech Republic| room: UI402 |
±--------------------------------------73-!-de-OK1INC@OK0PPL.#BOH.CZE.EU+
| Monday or Tuesday: | phone: +420 224 355 263 |
\_____________CESNET z.s.p.o.|location: Zikova 4, Prague//