rnaProduct.t 16.1 KB
Newer Older
1 2 3 4 5
# Copyright [2018] EMBL-European Bioinformatics Institute
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
Marek Szuba's avatar
Marek Szuba committed
6
#
7
#      http://www.apache.org/licenses/LICENSE-2.0
Marek Szuba's avatar
Marek Szuba committed
8
#
9 10 11 12 13 14
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

15 16 17 18
## no critic (RequireFilenameMatchesPackage)

package RNAProductTests;

19 20 21 22
use strict;
use warnings;

use Bio::EnsEMBL::Test::TestUtils;
23
use Bio::EnsEMBL::MicroRNA;
24
use Bio::EnsEMBL::RNAProduct;
25
use Bio::EnsEMBL::Transcript;
26 27 28

use Test::More;
use Test::Warnings;
29
use Test::Exception;
30 31

my $loaded = 0;
Marek Szuba's avatar
Marek Szuba committed
32
END { print "not ok 1 - Test set-up completed\n" unless $loaded; }
33 34 35 36 37 38 39

use Bio::EnsEMBL::Test::MultiTestDB;

my $multi = Bio::EnsEMBL::Test::MultiTestDB->new();

$loaded = 1;

Marek Szuba's avatar
Marek Szuba committed
40
ok(1, 'Test set-up completed');
41 42

my $db = $multi->get_DBAdaptor('core');
43
my $type_mapper = Bio::EnsEMBL::Utils::RNAProductTypeMapper::mapper();
44

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

#
# Tests for the RNAProductTypeMapper
#

subtest 'RNAProductTypeMapper tests' => sub {
  my $rpt_mapper = Bio::EnsEMBL::Utils::RNAProductTypeMapper->mapper();

  my $rpt_mapper2 = Bio::EnsEMBL::Utils::RNAProductTypeMapper->mapper();
  is($rpt_mapper, $rpt_mapper2, 'mapper() reuses existing instance if present');

  is($rpt_mapper->type_code_to_class('miRNA'), 'Bio::EnsEMBL::MicroRNA',
     'Can map existing type ID to class');
  dies_ok(sub { $rpt_mapper->type_code_to_class('semprini'); },
	  'Exception thrown on unknown type ID');

  is($rpt_mapper->class_to_type_code('Bio::EnsEMBL::RNAProduct'), 'generic',
     'Can map existing class to type ID');
  dies_ok(sub { $rpt_mapper->class_to_type_code('Bio::EnsEMBL::Storable'); },
	  'Exception thrown on unknown rnaproduct class name');
};


#
# Tests for offline RNAProduct objects
#

72 73
my $rp = Bio::EnsEMBL::RNAProduct->new();

Marek Szuba's avatar
Marek Szuba committed
74
ok($rp, 'RNAProduct constructor works without arguments');
75

Marek Szuba's avatar
Marek Szuba committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
# We will use the minimally constructed object from above for further
# testing so let us get rid of this one as soon as we are done with it.
{
  my %cta = (
    start => 123,
    end => 456,
    stable_id => 'ENSM00012345',
    version => 1337,
    dbID => 314,
    seq => 'ACGTACGT',
    created_date => time(),
    modified_date => time()
  );
  my $rp_with_args = Bio::EnsEMBL::RNAProduct->new(
    -SEQ_START => $cta{start},
    -SEQ_END => $cta{end},
    -STABLE_ID => $cta{stable_id},
    -VERSION => $cta{version},
    -DBID => $cta{dbID},
    -SEQ => $cta{seq},
    -CREATED_DATE => $cta{created_date},
    -MODIFIED_DATE => $cta{modified_date}
  );
  foreach my $member (sort keys %cta) {
    is($rp_with_args->{$member}, $cta{$member}, "RNAProduct constructor sets $member correctly");
  }
}

is($rp->version(), 1, 'Default rnaproduct version == 1');

ok(test_getter_setter($rp, 'start', 42), 'Test getter/setter start()');
ok(test_getter_setter($rp, 'end', 64), 'Test getter/setter end()');
ok(test_getter_setter($rp, 'stable_id', 1), 'Test getter/setter stable_id()');
ok(test_getter_setter($rp, 'dbID', 3), 'Test getter/setter dbID()');
ok(test_getter_setter($rp, 'version', 13), 'Test getter/setter version()');
ok(test_getter_setter($rp, 'created_date', time()), 'Test getter/setter created_date()');
ok(test_getter_setter($rp, 'modified_date', time()), 'Test getter/setter modified_date()');

114 115
is($rp->type_code(), $type_mapper->class_to_type_code(ref($rp)),
   'RNAProduct object has expected type code');
116

117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
subtest 'Test stable_id_version() functionality' =>  sub {
  ok(test_getter_setter($rp, 'stable_id_version', 3.14),
     'getter/setter with \'stable_id.version\' as input');
  ok(test_getter_setter($rp, 'stable_id_version', 'aqq'),
     'getter/setter with \'stable_id\' as input');

  # Let's be paranoid and assume test_getter_setter() cleans up after itself
  $rp->stable_id_version('ENSfoo.1');
  is($rp->stable_id_version(), $rp->stable_id() . '.' . $rp->version(),
     'set by stable_id_version(), get by stable_id() + version()');

  $rp->stable_id('ENSbar');
  $rp->version(9);
  is($rp->stable_id_version(), $rp->stable_id() . '.' . $rp->version(),
     'set by stable_id() + version(), get by stable_id_version()');
};

subtest 'display_id() functionality' =>  sub {
  # Start with a minimal object and gradually add missing data
  my $rp_blank = Bio::EnsEMBL::RNAProduct->new();

  is($rp_blank->display_id(), '',
     'return empty string if neither stable_id nor dbID exist');

  $rp_blank->dbID(12345);
  is($rp_blank->display_id(), $rp_blank->dbID(),
     'return dbID if no stable_id exists');

  $rp_blank->stable_id(54321);
  is($rp_blank->display_id(), $rp_blank->stable_id(),
     'return stable_id if it exists');
};

150
{
Marek Szuba's avatar
Marek Szuba committed
151
  dies_ok(sub { $rp->seq() }, 'Sequence getter dies if neither local nor DB data is available');
152 153 154 155
  # Again, assume test_getter_setter() cleans up after itself
  my $dummy_sequence = 'CGATCCGGAAAA';
  $rp->seq($dummy_sequence);
  is($rp->length(), length($dummy_sequence), 'Check if length() returns correct value');
Marek Szuba's avatar
Marek Szuba committed
156
  ok(test_getter_setter($rp, 'seq', 'AACCGGTT'), 'Test getter/setter seq()');
157
}
Marek Szuba's avatar
Marek Szuba committed
158

159 160
{
  dies_ok(sub { $rp->transcript({ }) }, 'Transcript setter dies on incorrect argument type');
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
  # The first step of test_getter_setter() is to preserve the existing value
  # of the property being tested. This is normally fine but in case of
  # transcript() invoking it as getter with no transcript previously having
  # been set causes it to attempt a database lookup, which:
  #  - is not desired because we are testing local functionality now, and
  #  - will fail because no adaptor has been set either.
  # Therefore, set a dummy transcript first. Then use a *different* dummy
  # transcript in the test to make sure the setter really works.
  # Nb. it is necessary to assign the first dummy transcript to a variable
  # because the setter uses a weak reference. If you simply use the return
  # value of the Transcript constructor as an argument to transcript(), the
  # former will get garbage-collected and the transcript will remain unset.
  my $dummy_transcript = Bio::EnsEMBL::Transcript->new();
  $rp->transcript($dummy_transcript);
  ok(test_getter_setter($rp, 'transcript', Bio::EnsEMBL::Transcript->new()), 'Test getter/setter transcript()');
176 177
}

178 179 180 181 182
is($rp->cdna_start(), $rp->start(),
   'Test if cdna_start() returns the same value as start()');
is($rp->cdna_end(), $rp->end(),
   'Test if cdna_end() returns the same value as end()');

183

184 185
#
# Tests for the mature-RNA adaptor
186
#
187 188 189

my $rp_a  = $db->get_RNAProductAdaptor();

Marek Szuba's avatar
Marek Szuba committed
190
ok($rp_a, 'Can get RNAProductAdaptor from core DBAdaptor');
191

192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
is($rp_a->fetch_by_dbID(0), undef, 'Adaptor returns undef for nonexistent dbID');
is($rp_a->fetch_by_stable_id('fnord'), undef, 'Adaptor returns undef for nonexistent stable ID');

subtest 'fetch_all_by_Transcript() functionality' => sub {
  my $t_a = $db->get_TranscriptAdaptor();
  my $rps;
  my $t;

  $t = Bio::EnsEMBL::Transcript->new();
  $rps = $rp_a->fetch_all_by_Transcript($t);
  isa_ok($rps, 'ARRAY', 'fetch_all_by_Transcript() return value');
  is(scalar @{$rps}, 0, 'Adaptor returns empty list for invalid Transcript');

  $rps = undef;
  $t = $t_a->fetch_by_dbID(21716);
  $rps = $rp_a->fetch_all_by_Transcript($t);
  is(scalar @{$rps}, 0, 'Adaptor returns empty list for Transcript with no RNA products');

  $rps = undef;
  $t = $t_a->fetch_by_dbID(21717);
  $rps = $rp_a->fetch_all_by_Transcript($t);
  # Do not bother checking if elements of the returned array are defined,
  # we are testing the method and not database consistency.
  cmp_ok(scalar @{$rps}, '>', 0, 'Non-empty list for Transcript with RNA products');
};

218
subtest 'fetch_all_by_type() functionality' => sub {
219 220 221 222 223
  my $n_rps;

  # At the moment we have only got miRNA in the homo_sapiens test database

  # FIXME: compare this to the total number of RNAProducts?
224 225 226 227
  $n_rps = scalar @{$rp_a->fetch_all_by_type('miRNA')};
  cmp_ok($n_rps, '>', 0, 'Got non-empty list of miRNA rnaproducts');
  $n_rps = scalar @{$rp_a->fetch_all_by_type('generic')};
  cmp_ok($n_rps, '==', 0, 'Got empty list of generic rnaproducts');
228 229
};

230 231 232 233 234 235 236 237
$rp = undef;
$rp = $rp_a->fetch_by_dbID(1);
ok($rp, 'Can fetch RNAProduct by dbID');

$rp = undef;
$rp = $rp_a->fetch_by_stable_id('ENSM00000000001');
ok($rp, 'Can fetch RNAProduct by stable ID');

238
isa_ok($rp, 'Bio::EnsEMBL::MicroRNA', 'miRNA object from database');
239 240
is($rp->type_code(), $type_mapper->class_to_type_code(ref($rp)),
   'MicroRNA object has expected type code');
241

242 243 244 245
# FIXME: perform an in-depth inspection of one of the fetched RNAProducts,
# to make sure new_fast() call all of these fetch methods use does what it
# is supposed to do.

Marek Szuba's avatar
Marek Szuba committed
246 247
is($rp->seq(), 'AAAAACCCAGGAATCACCTGGA', 'Can retrieve associated sequence');

248 249 250 251 252 253 254
# Do not check any data inside the Transcript object, it is not our job to
# check database consistency. Just check that we do get something back.
isnt($rp->transcript(), undef, 'Can retrieve associated Transcript object');

# And now, force the Transcript association to be built on the fly.
$rp->transcript(undef);
isnt($rp->transcript(), undef, 'Transcript association can be built on demand for valid dbID');
255

256 257 258 259 260 261
# FIXME: might want to add tests for the reverse strand as well
is($rp->genomic_start(), $rp->transcript()->start() + $rp->start() - 1,
   'genomic_start() gives correct values (forward strand)');
is($rp->genomic_end(), $rp->transcript()->start() + $rp->end() - 1,
   'genomic_end() gives correct values (forward strand)');

262

263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294
subtest 'Attribute functionality' => sub {
  my $rp_all_attrs = $rp->get_all_Attributes();
  cmp_ok(scalar @$rp_all_attrs, '>', 0, 'Get a non-empty list of attributes');

  my $rp_notes = $rp->get_all_Attributes('note');
  cmp_ok(scalar @$rp_notes, '>', 0, 'Get a non-empty list of \'note\' attributes');

  my $rp_nonsense = $rp->get_all_Attributes('xyzzy');
  is(scalar @$rp_nonsense, 0, 'Get empty attribute list for nonsense code');

  dies_ok(sub { $rp->add_Attributes({}) },
	  'add_Attributes() dies on invalid argument type');

  my $n_attrs_before = scalar @$rp_all_attrs;
  my $extra_attr1 = Bio::EnsEMBL::Attribute->new(
    -CODE => 'note',
    -NAME => 'Note',
    -VALUE => 'and another thing'
  );
  my $extra_attr2 = Bio::EnsEMBL::Attribute->new(
    -CODE => '_rna_edit',
    -VALUE => '1 6 GATTACA',
    -NAME => 'RNA editing'
  );
  $rp->add_Attributes($extra_attr1, $extra_attr2);
  is(scalar @{$rp->get_all_Attributes()}, scalar $n_attrs_before + 2, 'Added two new attributes');

  # FIXME: Add SeqEdit tests once we have got some meaningful data for this
  # in the test database. The way this is done in Transcript tests ought to
  # be a good reference.
};

295

Marek Szuba's avatar
Marek Szuba committed
296 297
subtest 'xref functionality' => sub {
  my $xrefs = $rp->get_all_DBEntries();
298
  cmp_ok(scalar @$xrefs, '>', 0, 'Got a non-empty list of DBEntries');
Marek Szuba's avatar
Marek Szuba committed
299 300 301 302 303 304 305 306

  dies_ok(sub { $rp->add_DBEntry({}) },
	  'add_DBEntry() dies on invalid argument type');

  my $n_xrefs_before = scalar @$xrefs;
  my $dbe = Bio::EnsEMBL::DBEntry->new(
    -primary_id => 'test_id',
    -version    => 1,
307
    -dbname     => 'miRNA_Registry',
Marek Szuba's avatar
Marek Szuba committed
308 309 310 311 312 313 314 315 316 317 318 319 320 321
    -display_id => 'test_id'
  );
  $rp->add_DBEntry($dbe);
  is(scalar @{$rp->get_all_DBEntries()}, scalar $n_xrefs_before + 1, 'Added one new xref');

  # No need for deep comparisons here, these four methods are supposed
  # to return literally the same reference
  is($xrefs, $rp->get_all_object_xrefs(),
     'get_all_object_xrefs() is a alias of get_all_DBEntries()');
  is($xrefs, $rp->get_all_DBLinks(),
     'get_all_DBLinks() is a alias of get_all_DBEntries()');
  is($xrefs, $rp->get_all_xrefs(),
     'get_all_xrefs() is a alias of get_all_DBEntries()');
};
322

323 324 325
my $rp_exts = $rp_a->fetch_all_by_external_name('hsa-miR-1-3p');
cmp_ok(scalar @$rp_exts, '>', 0, 'Can fetch RNAProduct by external ID');

326 327 328
# Test generic_count(), inherited method from BaseAdaptor
is($rp_a->generic_count(), @{$rp_a->list_dbIDs()}, "Number of features from generic_count is equal to the number of dbIDs from list_dbIDs");

329

330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355
#
# MicroRNA-specific tests
#

subtest 'MicroRNA tests' => sub {
  my $mirna;

  $mirna = Bio::EnsEMBL::MicroRNA->new();
  ok($mirna, 'MicroRNA constructor works without arguments');
  isa_ok($mirna, 'Bio::EnsEMBL::MicroRNA', 'miRNA object from new()');

  $mirna = Bio::EnsEMBL::MicroRNA->new(
    -SEQ_START => 314,
    -ARM => 3
  );
  ok($mirna, 'MicroRNA constructor works with arguments');
  is($mirna->arm(), 3, 'MicroRNA-specific parameters set OK');
  is($mirna->start(), 314, 'Generic RNAProduct parameters set OK');

  $mirna = $rp_a->fetch_by_dbID(1);
  ok($mirna, 'Can fetch MicroRNA from RNAProductAdaptor');
  isa_ok($mirna, 'Bio::EnsEMBL::MicroRNA', 'miRNA object from RNAProductAdaptor');
  isnt($mirna->arm(), undef, 'Can retrieve miRNA arm value from DB');
};


356
#
357 358
# Operations which modify database entries
#
359

360 361 362 363 364 365
subtest 'Write operations' => sub {
  my $rp_count = count_rows($db, 'rnaproduct');
  my $rp_attr_count = count_rows($db, 'rnaproduct_attrib');
  my $object_xref_count = count_rows($db, 'object_xref');
  my $xref_count = count_rows($db, 'xref');
  $multi->save('core', 'rnaproduct', 'rnaproduct_attrib', 'object_xref', 'xref');
366

367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
  my $t_a = $db->get_TranscriptAdaptor();
  my $ins_parent = $t_a->fetch_by_dbID(21728);

  my %insert_args = (
    start         => 6,
    end           => 27,
    stable_id     => 'ENSM00000000099',
    version       => 1,
    created_date  => time(),
    modified_date => time(),
    arm           => 5,
  );
  my $ins_rp = Bio::EnsEMBL::MicroRNA->new(
    -SEQ_START     => $insert_args{start},
    -SEQ_END       => $insert_args{end},
    -STABLE_ID     => $insert_args{stable_id},
    -VERSION       => $insert_args{version},
    -CREATED_DATE  => $insert_args{created_date},
    -MODIFIED_DATE => $insert_args{modified_date},
    -ARM           => $insert_args{arm},
  );
  my $ins_dbe = Bio::EnsEMBL::DBEntry->new(
    -primary_id => 'MIMAT0000062',
    -version    => 1,
    -dbname     => 'miRNA_Registry',
    -display_id => 'hsa-let-7a-5p',
  );
  is($ins_rp->dbID(), undef, 'MicroRNA dbID not defined before storing');
  $ins_rp->add_DBEntry($ins_dbe);
  $rp_a->store($ins_rp, $ins_parent->dbID());
  isnt($ins_rp->dbID(), undef, 'MicroRNA dbID defined after storing');
  is($ins_rp->adaptor(), $rp_a,
     'MicroRNA linked to RNAPRoductAdaptor after storing');
  is(count_rows($db, 'rnaproduct'), $rp_count + 1,
     'Post-store rnaproduct row count correct');
  is(count_rows($db, 'rnaproduct_attrib'), $rp_attr_count + 1,
     'Post-store rnaproduct_attrib row count correct');
  is(count_rows($db, 'object_xref'), $object_xref_count + 1,
     'Post-store object_xref row count correct');
  is(count_rows($db, 'xref'), $xref_count + 1,
     'Post-store xref row count correct');

  my $fetched_rp = $rp_a->fetch_by_dbID($ins_rp->dbID());
  for my $method (keys %insert_args) {
    is($fetched_rp->$method(), $insert_args{$method},
       "RNAProduct from database has correct $method value");
  }
  is(scalar @{ $fetched_rp->get_all_Attributes() }, 1,
     'Fetched MicroRNA has correct number of attributes');
  is(scalar @{ $fetched_rp->get_all_DBEntries() }, 1,
     'Fetched MicroRNA has correct number of xrefs');
  isnt($fetched_rp->transcript(), undef,
       'Fetched MicroRNA has a parent transcript');

  my $del_rp = $rp_a->fetch_by_dbID(1);
  $rp_a->remove($del_rp);
  is($del_rp->dbID(), undef, 'Removed MicroRNA has no dbID');
  is($del_rp->adaptor(), undef, 'Removed MicroRNA not linked to adaptor');
  is(count_rows($db, 'rnaproduct'), $rp_count,
     'Post-remove rnaproduct row count correct');
  is(count_rows($db, 'rnaproduct_attrib'), $rp_attr_count - 1,
     'Post-remove rnaproduct_attrib row count correct');
  is(count_rows($db, 'object_xref'), $object_xref_count,
     'Post-remove object_xref row count correct');
  # Not a mistake, actual xrefs do NOT get removed by
  # DBEntryAdaptor::remove_from_object(). See e.g. Doxygen docs
  # for that method.
  is(count_rows($db, 'xref'), $xref_count + 1,
     'Post-remove xref row count correct');
  is ($rp_a->fetch_by_dbID(1), undef,
      'Fetching removed MicroRNA returns undef');

  $multi->restore('core', 'rnaproduct', 'rnaproduct_attrib', 'object_xref', 'xref');
440 441 442
};


443
done_testing();
444 445

1;