NAME

Test::Neo4j::Types - Tools for testing Neo4j type modules

VERSION

version 0.01

SYNOPSIS

# For a node class that happens to have a new()
# constructor with parameters that match the ones
# given here exactly:
neo4j_node_ok 'Local::Node', \&Local::Node::new;

# For a node data structure that happens to match
# the given parameters exactly:
neo4j_node_ok 'Local::Node', sub {
  my ($class, $params) = @_;
  return bless { %$params }, $class;
};

# For a relationship data structure that needs
# adapting from the given parameters:
neo4j_relationship_ok 'Local::Reln', sub {
  my ($class, $params) = @_;
  return bless {
    %$params,
    start => $params->{start_id},
    end   => $params->{end_id},
  }, $class;
};

# For the typical path data structure:
neo4j_path_ok 'Local::Path', sub {
  my ($class, $elements) = @_;
  return bless [ @$elements ], $class;
};

# For a point data structure:
neo4j_point_ok 'Local::Point';

DESCRIPTION

Offers a simple way to test your Neo4j::Types implementation for correctness. These test tools not only verify that the required methods are provided, they also try to verify that the methods actually work as expected. While the checks provided by this module certainly won't cover all requirements, they will cover many of them.

OVERVIEW

This module distribution is experimental. Should the experiment be deemed successful, it will eventually be merged with the existing Neo4j-Types distribution.

You probably shouldn't be using this module at this time, because the requirements it checks for are evolving and might shift under your feet at any moment. For further information, see johannessen/neo4j-types Version 2 (milestone).

FUNCTIONS

Test::Neo4j::Types offers the following functions. All functions are exported by default.

neo4j_node_ok

sub node_new ($class, $params) {
  return bless { ... }, $class;
}
neo4j_node_ok $node_class, \&node_new;
neo4j_node_ok $node_class, \&node_new, $subtest_name;

Verifies that $node_class is a package that implements the interface specified for nodes by Neo4j::Types.

\&node_new must be a reference to a subroutine that can construct a new node of the type $node_class based on the parameters provided in the hash ref $params. The parameters have names exactly matching the methods in Neo4j::Types::Node:

$params = {
  element_id => '4:a9bd8c39-9afb-4474-9890-c074b2002cf5:47',
  id         => 47,
  labels     => ['Label'],
  properties => { key => 'value' },
};

neo4j_path_ok

sub path_new ($class, $elements) {
  return bless [ @$elements ], $class;
}
neo4j_path_ok $path_class, \&path_new;
neo4j_path_ok $path_class, \&path_new, $subtest_name;

Verifies that $path_class is a package that implements the interface specified for paths by Neo4j::Types.

\&path_new must be a reference to a subroutine that can construct a new path of the type $path_class based on the elements provided in the array ref $elements. The elements are alternating between references that represent nodes and relationships in the exact same order as for "elements" in Neo4j::Types::Path:

$elements = [
  $node_0,
  $relationship_0,
  $node_1,
  $relationship_1,
  $node_2,
];

Inside path_new, these references will purport to perform the Neo4j::Types::Node and Neo4j::Types::Relationship roles, but shall be treated as opaque. Calling any methods other than ->DOES() on these references may fail.

neo4j_point_ok

neo4j_point_ok $point_class;
neo4j_point_ok $point_class, $subtest_name;

Verifies that $point_class is a package that implements the interface specified for spatial points by Neo4j::Types.

Note that unlike the other test tools, this one doesn't need a constructor sub reference. Neo4j::Types::Point requires one anyway because Point is a Neo4j property type, which means it should in theory be possible to construct points without using Cypher. (However, passing of Point values as parameters is not currently implemented in any known CPAN module.)

With all that said, this test tool may change in future, even independent of the reasons stated in "BUGS AND LIMITATIONS".

neo4j_relationship_ok

sub rel_new ($class, $params) {
  return bless { ... }, $class;
}
neo4j_relationship_ok $rel_class, \&rel_new;
neo4j_relationship_ok $rel_class, \&rel_new, $subtest_name;

Verifies that $rel_class is a package that implements the interface specified for relationships by Neo4j::Types.

\&rel_new must be a reference to a subroutine that can construct a new relationship of the type $rel_class based on the parameters provided in the hash ref $params. The parameters have names exactly matching the methods in Neo4j::Types::Relationship:

$params = {
  element_id       => '5:a9bd8c39-9afb-4474-9890-c074b2002cf5:23',
  id               => 23,
  start_element_id => '4:a9bd8c39-9afb-4474-9890-c074b2002cf5:81',
  start_id         => 81,
  end_element_id   => '4:a9bd8c39-9afb-4474-9890-c074b2002cf5:82',
  end_id           => 82,
  properties       => { key => 'value' },
  type             => 'TYPE',
};

BUGS AND LIMITATIONS

The diagnostics are not particularly great. All of these tools are implemented as simple subtests. You can run prove -v and obtain details about any failing checks, but you'll probably have to compare the TAP output with this modules's source code to make sense of them. Unfortunately, the tool source code is more optimised for compactness that for readability, which of course means me asking people to "just read the code" is quite shameless. However, because the number of users this module is anticipated to have is very low (maybe two or so), this limitation is unlikely to be addressed.

The individual test names inside the subtests could be (and probably should be) improved though. Ideally, the names of failed tests would make sense even without reading the source.

As a consequence of the subtests, it appears to be difficult to verify that these tools correctly identify non-conforming implementations, which is of course the primary job of these tools. So the testing of the tools themselves is incomplete.

Optional / "should" requirements may need to be checked, with warnings or at least diag messages issued if not met. These warnings need to be individually selectable. One (naive but perhaps adequate) way to implement this might be a global @Test::Neo4j::Types::no_warnings variable, which users could then localise and configure as required.

If these tools are ever developed further than this, switching to Test2::Manual::Tooling should be considered.

SEE ALSO

Neo4j::Types::ImplementorNotes

AUTHOR

Arne Johannessen <ajnn@cpan.org>

If you contact me by email, please make sure you include the word "Perl" in your subject header to help beat the spam filters.

COPYRIGHT AND LICENSE

This software is Copyright (c) 2023 by Arne Johannessen.

This is free software; you can redistribute it and/or modify it under the terms of the Artistic License 2.0 or (at your option) the same terms as the Perl 5 programming language system itself.