Most core and many contrib simpletest test create nodes by preparing the interface, logging an admin in and then filling out the form on /node/add/foo
. Not only is this terribly slow, it fails at the most basic rule of Testing: only test your own concerns; mock and stub the rest.
For a test, all I need is N nodes with X tags (taxonomy-terms) attached to them. I am (in no way) interested in whether or not some "Save" button exists somewhere; which is what I am testing when I follow along with core tests, e.g my helper function createNodesWithTags()
.
This helper is modeled after TaxonomyRSSTestCase
which has the same concern as my: make sure there are some nodes with tags, so that some interface can then be tested using these nodes. The helper first creates an entity-field on the node type "article", required because otherwise one cannot add tags to that node. It then proceeds to open up the node/add/article
-page, attaches the term and presses Save
.
private function createNodesWithTags($amount) {
$field = array(
'field_name' => 'taxonomy_' . $this->vocabulary->machine_name,
'type' => 'taxonomy_term_reference',
'cardinality' => FIELD_CARDINALITY_UNLIMITED,
'settings' => array(
'allowed_values' => array(
array(
'vocabulary' => $this->vocabulary->machine_name,
'parent' => 0,
),
),
),
);
field_create_field($field);
$this->instance = array(
'field_name' => 'taxonomy_' . $this->vocabulary->machine_name,
'bundle' => 'article',
'entity_type' => 'node',
'widget' => array(
'type' => 'options_select',
),
'display' => array(
'default' => array(
'type' => 'taxonomy_term_reference_link',
),
),
);
field_create_instance($this->instance);
//Create N nodes and attach all N to tag1, N-1 to tag2, N-2 to tag3 etc.
$attachable = $this->tags;
for ($i = 0; $i < $amount; $i++) {
// Post an article.
$edit = array();
$langcode = LANGUAGE_NONE;
$edit["title"] = $this->randomName();
foreach($attachable as $tag) {
$edit[$this->instance['field_name'] . '[' . $langcode . '][]'] = $tag->tid;
}
$this->drupalPost('node/add/article', $edit, t('Save'));
//remove one tag, so the next node gets one less tag attached.
array_shift($attachable);
}
}
Why do core tests test this way? Why is TaxonomyTestCase concerned with whether or not saving a node works (i.e. an admin can be created, logged in and finds the Save button)? Why don't they just call node_save()
or some other API?
Is there a reason why I should implement it this way too, instead of just dropping records in the database, possible trough the node_save()
API?
node_save()
manually. The submit handler for the node add form does that anyway after attaching the fields from the form submission, so if you've attached the required fields yourself and validated them you're just doing the same thing but bypassing the form mechanism