Problem/Motivation

Status

The issue has been open since 2009. It has consensus and the approval of SimpleTest maintainers, and is already part of our documented standard:
http://drupal.org/simpletest-tutorial-drupal7#t

Details

  • The $message parameter of SimpleTest assertions (e.g., DrupalTestCase::assertTrue()) is a string displayed only in the administrative UI or on the commandline following test runs, and on testbot.
  • This parameter is never translated, so using t() on it is needless overhead.
  • We have other instances in core where string function parameters should not be wrapped in t(), e.g. watchdog().
  • When the assertion message is a plain string, t() should simply be omitted.
  • When the assertion message contains placeholders for variables, format_string() should be used instead.

Proposed resolution

  • Strip t() from plain-string assertion messages that are still using it.
    • $this->assertWhatever($condition, t('My custom message here'));
      

      Becomes:

       $this->assertWhatever($condition, 'My custom message here');
      
    • Assertion messages that have placeholders or variables will be converted to format_string(). This can be done separately if the patch is particularly large. (Mark issues that have already had messages with placeholders converted in the list below.)
    • Other parameters of assertions (beside the message parameter) are not changed.
    • Other uses of t() in automated tests are not changed.
  • Discuss other uses of t() in tests in a separate issue.
  • Consider documenting this practice in the parameter documentation for assertions in a followup issue.

Remaining tasks

  1. Generate patches stripping t() from plain-string assertion messages only (issues below).
  2. Review these patch closely to ensure there are no incorrect changes. Applying locally and using git diff --color-words works well.
  3. Address assertion messages with placeholders separately if the patch is large.
  4. Address followup issues separately.
  5. Post a change notice.

What parts of core are affected?

How will we avoid conflicts with important patches?

  • Testing in July shows=ed that only 4 patches out of 900-some NR 8.x issues were affected by this change.
  • There is no affect on patches that do not include changes to existing automated tests.
  • With no moved files or lines and a simple 1:1 assertion/deletion, the change is straightforward enough that, in most cases, patches and sandboxes can simply be rebased to make them apply on top of the change.
  • We will ensure all issues with the Avoid commit conflicts tag have a compatible reroll in the issue before the change is committed. If you have an important outstanding issue that is close to being RTBC, please add this tag to that issue.
  • If you have an important sandbox for which we should avoid merge conflicts, please post a comment below. Link the sandbox's project page and identify the relevant branch(es).

Related issues

Original report by neochief

Hello.

As one of the active Russian translators, I can state that translation of simpletests asserts' descriptions is totally useless (as it was once before in Schema descriptions). People who run tests are familiar with English.

Maybe we should consider removing those t() from our tests?

CommentFileSizeAuthor
#280 500866-280-d8-grep.txt29.68 KBstar-szr
#280 500866-280-d7-grep.txt40.19 KBstar-szr
#225 most_recent.txt45.58 KBxjm
#225 rtbc_and_nr_patches.tar_.gz1.72 MBxjm
#224 assert-t.csv_.zip218.03 KBwebchick
#220 test_and_rebase_patches.sh_.txt1.79 KBxjm
#218 assert-t.csv_.zip1.28 MBwebchick
#209 assert_t.sh_.txt240 bytesZenDoodles
#206 interdiff.txt4.95 KBZenDoodles
#206 assert_t-500866-206.patch1.21 MBZenDoodles
#205 interdiff.txt4.96 KBZenDoodles
#205 assert_t-500866-205.patch1.21 MBZenDoodles
#203 rewrite-tests-t.sh_.txt194 bytessun
#201 interdiff.txt807.41 KBZenDoodles
#201 assert_t-500866-201.patch1.21 MBZenDoodles
#199 rewrite-tests-t.sh_.txt185 bytessun
#199 rewrite-tests-t.199.patch1.29 MBsun
#191 assert_t-500866-191.patch1.29 MBZenDoodles
#168 500866-remove-t.patch1.47 MBsolotandem
#163 simpletest_remove_t-500866-163.patch1.69 MBpillarsdotnet
#161 500866-remove-t_6.patch1.47 MBsolotandem
#154 simpletest_remove_t-500866-154.patch1.75 MBpillarsdotnet
#152 simpletest_remove_t-500866-152.patch1.75 MBpillarsdotnet
#150 simpletest_remove_t-500866-150.patch1.75 MBpillarsdotnet
#148 simpletest_remove_t-500866-148.patch1.75 MBpillarsdotnet
#146 simpletest_remove_t-500866-146.patch1.75 MBpillarsdotnet
#142 simpletest_remove_t-500866-142.patch1.75 MBpillarsdotnet
#140 simpletest_remove_t-500866-140.patch1.75 MBpillarsdotnet
#137 simpletest_remove_t-500866-137.patch1.75 MBpillarsdotnet
#135 simpletest_remove_t-500866-135.patch1.75 MBpillarsdotnet
#134 simpletest_remove_t-500866-134.patch1.72 MBpillarsdotnet
#133 simpletest_remove_t-500866-133.patch1.72 MBpillarsdotnet
#131 simpletest_remove_t-500866-131.patch1.72 MBpillarsdotnet
#125 500866-remove-t_5.patch1.44 MBsolotandem
#123 500866-remove-t_4.patch1.44 MBsolotandem
#113 remove-unnecessary-t-from-assert.patch1.2 MBpillarsdotnet
#112 remove-unnecessary-t-from-assert.patch1.19 MBpillarsdotnet
#110 remove-unnecessary-t-from-assert.patch1.19 MBpillarsdotnet
#100 500866-non-translating-translator.patch1.47 KBDamien Tournoud
#88 500866-remove-t.patch1.26 MBboombatower
#86 500866-remove-t.patch256.75 KBboombatower
#84 500866-remove-t.patch99.89 KBboombatower
#82 500866-remove-t.patch1.23 MBboombatower
#80 500866-remove-t.patch1.23 MBsolotandem
#77 500866-remove-t.patch1.23 MBsolotandem
#59 500866-remove-t.patch1.05 MBboombatower
#57 500866-remove-t.patch1.05 MBboombatower
#53 500866-remove-t.patch1.06 MBboombatower
#49 500866-remove-t.patch1.09 MBboombatower
#47 500866-remove-t.patch1.09 MBboombatower
#45 500866-remove-t.patch1.09 MBboombatower
#31 field_test_translations.patch2.33 KByched
#27 500866-remove-t.patch111.09 KBboombatower
#15 500866-remove-t.patch110.59 KBboombatower
#14 500866-remove-t.patch724.92 KBboombatower
#12 500866-remove-t.patch724.92 KBboombatower
#10 500866-remove-t.patch728.08 KBboombatower
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

boombatower’s picture

I completely agree...and have meant to start this issue for a while.

+1

boombatower’s picture

Title: Simpletest: useless t() in assert descriptions. » Simpletest: remove t() form assert message, test getInfo(), etc

Do we even want to remove it from button text.

I understand buttons are translated, but if we are assuming English then what is the point of translating the test. The only exception may be in the locale tests and such, but that makes sense.

Thoughts?

neochief’s picture

Nice to hear that. I'm not sure that I undertood you right, Jimmy, but as for me, we should remove translation of meta-data (descriptions, test group names, etc) only. Other things like text, should be tested (asserted, submitted, etc) just like it appears in Drupal code.

neochief’s picture

Issue tags: +Simpletest
boombatower’s picture

Right, so remove all meta data and strings not related to the code being tested.

For example, the following would be the new convention:

$this->assertTrue(TRUE, 'Text explaining the result');

$edit = array(...);
$this->drupalPost('some/url', $edit, t('Button text'));

public static function getInfo() {
  return array(
    'name' => 'Test name',
    'description' => 'Test description',
    'group' => 'Test group',
  );
}
neochief’s picture

Yes, you're completelly right.

chx’s picture

Go for it. I thought we agreed on this ages ago?

Dave Reid’s picture

Yes. Webchick and I had discussed this before a couple months ago. Using t() in tests only makes sense if you need the placeholder/checkplain replacement or you are looking for a specific button that could be translated, like the drupalPost() $submit parameter.

boombatower’s picture

Assigned: Unassigned » boombatower

Working on this.

boombatower’s picture

Status: Active » Needs review
FileSize
728.08 KB

Need to see if there are any other invalid t() instances. Plus I want to see what bot thinks.

Used to following script.

foreach (file_scan_directory('modules', '/\.test$/') as $file) {
  $contents = file_get_contents($file->filepath);

  // Run twice to ensure that second parameters get picked up as well and
  // be safe with 4 run throughs.
  for ($i = 0; $i < 4; $i++) {
    $contents = preg_replace('/(assert\w+\(.*?,.*?)t\(([\'|"].*?[\'|"])\)/', '\1\2', $contents);
  }

  // Clean getInfo() methods.
  $contents = preg_replace('/(getInfo\(\).*?)t\((.*?)\)(.*?)t\((.*?)\)(.*?)t\((.*?)\)/s', '\1\2\3\4\5\6', $contents);

  file_put_contents($file->filepath, $contents);

  echo 'Cleaned: ' . $file->filepath . "\n";
}

following output:

Cleaned: modules/openid/openid.test
Cleaned: modules/tracker/tracker.test
Cleaned: modules/book/book.test
Cleaned: modules/blogapi/blogapi.test
Cleaned: modules/blog/blog.test
Cleaned: modules/syslog/syslog.test
Cleaned: modules/path/path.test
Cleaned: modules/node/node.test
Cleaned: modules/filter/filter.test
Cleaned: modules/system/system.test
Cleaned: modules/php/php.test
Cleaned: modules/menu/menu.test
Cleaned: modules/field/modules/field_sql_storage/field_sql_storage.test
Cleaned: modules/field/modules/text/text.test
Cleaned: modules/field/field.test
Cleaned: modules/locale/locale.test
Cleaned: modules/forum/forum.test
Cleaned: modules/statistics/statistics.test
Cleaned: modules/upload/upload.test
Cleaned: modules/simpletest/tests/form.test
Cleaned: modules/simpletest/tests/session.test
Cleaned: modules/simpletest/tests/registry.test
Cleaned: modules/simpletest/tests/module.test
Cleaned: modules/simpletest/tests/unicode.test
Cleaned: modules/simpletest/tests/theme.test
Cleaned: modules/simpletest/tests/bootstrap.test
Cleaned: modules/simpletest/tests/menu.test
Cleaned: modules/simpletest/tests/error.test
Cleaned: modules/simpletest/tests/filetransfer.test
Cleaned: modules/simpletest/tests/database_test.test
Cleaned: modules/simpletest/tests/file.test
Cleaned: modules/simpletest/tests/common.test
Cleaned: modules/simpletest/tests/xmlrpc.test
Cleaned: modules/simpletest/tests/schema.test
Cleaned: modules/simpletest/tests/image.test
Cleaned: modules/simpletest/tests/actions.test
Cleaned: modules/simpletest/tests/cache.test
Cleaned: modules/simpletest/tests/graph.test
Cleaned: modules/simpletest/tests/batch.test
Cleaned: modules/simpletest/simpletest.test
Cleaned: modules/dblog/dblog.test
Cleaned: modules/aggregator/aggregator.test
Cleaned: modules/user/user.test
Cleaned: modules/profile/profile.test
Cleaned: modules/contact/contact.test
Cleaned: modules/taxonomy/taxonomy.test
Cleaned: modules/search/search.test
Cleaned: modules/poll/poll.test
Cleaned: modules/trigger/trigger.test
Cleaned: modules/translation/translation.test
Cleaned: modules/help/help.test
Cleaned: modules/comment/comment.test
Cleaned: modules/block/block.test

Status: Needs review » Needs work

The last submitted patch failed testing.

boombatower’s picture

Status: Needs work » Needs review
FileSize
724.92 KB

This script fixes two issues:

foreach (file_scan_directory('modules', '/\.test$/') as $file) {
  $contents = file_get_contents($file->filepath);

  // Run twice to ensure that second parameters get picked up as well and
  // be safe with 4 run throughs.
  for ($i = 0; $i < 4; $i++) {
    $contents = preg_replace('/(assert\w+\(.*?,.*?) t\(([\'|"].*?[\'|"])\)/', '\1\2', $contents);
  }

  // Clean getInfo() methods.
  $contents = preg_replace('/(getInfo\(\).*?)t\(([\'|"].*?[\'|"])\)(.*?)t\(([\'|"].*?[\'|"])\)(.*?)t\(([\'|"].*?[\'|"])\)/s', '\1\2\3\4\5\6', $contents);

  file_put_contents($file->filepath, $contents);

  echo 'Cleaned: ' . $file->filepath . "\n";
}

Status: Needs review » Needs work

The last submitted patch failed testing.

boombatower’s picture

Status: Needs work » Needs review
FileSize
724.92 KB

Focus on getInfo() to get a good patch.

foreach (file_scan_directory('modules', '/\.test$/') as $file) {
  $contents = file_get_contents($file->filepath);

  // Run twice to ensure that second parameters get picked up as well and
  // be safe with 4 run throughs.
//  for ($i = 0; $i < 4; $i++) {
//    $contents = preg_replace('/(assert\w+\(.*?,.*? )t\(([\'|"].*?[\'|"])\)/', '\1\2', $contents);
//  }

  // Clean getInfo() methods, allow for some to be not t()'ed.
  $contents = preg_replace('/(getInfo\(\).*?name.*?)t\(([\'|"].*?[\'|"])\)(.*?})/s', '\1\2\3', $contents);
  $contents = preg_replace('/(getInfo\(\).*?description.*?)t\(([\'|"].*?[\'|"])\)(.*?})/s', '\1\2\3', $contents);
  $contents = preg_replace('/(getInfo\(\).*?group.*?)t\(([\'|"].*?[\'|"])\)(.*?})/s', '\1\2\3', $contents);

  file_put_contents($file->filepath, $contents);

  $last = exec('php -l ' . $file->filepath);
  if (substr($last, 0, 2) != 'No') {
    echo '  Clean failed: ' . $file->filepath . "\n";
  }
  else {
    echo 'Cleaned: ' . $file->filepath . "\n";
  }
}
boombatower’s picture

FileSize
110.59 KB

Managed to upload old patch.

Dave Reid’s picture

Status: Needs review » Reviewed & tested by the community

Patch applied cleanly and I couldn't find any instances of t() in core getInfo() functions.

drewish’s picture

oh man i'm so excited about this. finally a mega patch i can get behind.

webchick’s picture

This makes sense. I'm just pondering when is the most logical time to commit this.

Dries’s picture

I support this patch as well.

boombatower’s picture

I would really like to see this get in since its ready to go, rather then rotting and having to be re-rolled repeatedly.

After this initial patch, the secondary chunk needs to be rolled so I think we should try and get this in.

The first patch creates minimal disturbance for patches since it only touches the getInfo() stuff which most patches aren't touching.

drewish’s picture

I'd say do it sooner than later. It's going to be a hassle either way so no sense having it looming over us for a few weeks.

Damien Tournoud’s picture

I'm +1 on committing that right now. As far as I know, we don't have a lot of patches affecting tests right now.

Status: Reviewed & tested by the community » Needs work

The last submitted patch failed testing.

boombatower’s picture

I'll wait til I get confirmation that this will get committed when I post. This is the exact reason I wanted to get on with it...so I don't have to re-roll endlessly.

boombatower’s picture

Status: Needs work » Needs review
FileSize
111.09 KB

Talked with webchick in IRC, she said it would be alright.

boombatower’s picture

Status: Needs review » Reviewed & tested by the community

Guess it should be bumped up as it was before.

webchick’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs documentation

Committed to HEAD. Docs need updating.

boombatower’s picture

Also, this issue has a much larger change: cleaning up the assertions as described above. Not sure what the thoughts are on when to commit that.

It is much larger patch and I don't want to start rolling it until we are ready to commit. Seems like there is concern that it isn't worth committing it if it screws up patches and slows development. I am ok with postponing as long as it gets in before D7 release. Not sure if something like this can get in after freeze?

One advantage for sooner is when people start upgrading the standard will be set.

I will work on updating docs.

yched’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
2.33 KB

field.test got left out - probably because of the double spacing in front of the => which failed regexp replace ?
Being bold and setting to RTBC.

boombatower’s picture

Looks good...fixed formatting error as well.

Damien Tournoud’s picture

Title: Simpletest: remove t() form assert message, test getInfo(), etc » Simpletest: remove t() from assert message, test getInfo(), etc

Status: Reviewed & tested by the community » Needs work

The last submitted patch failed testing.

yched’s picture

bleh, nevermind, field.test had been fixed in the committed patch, forget about #31.
Leaving to 'needs work', where it was before I started being a dumba**.

boombatower’s picture

Hehe.

hass’s picture

+

hass’s picture

Sometimes I've used assert messages like t('Link check for %url is disabled.', array('%url' => $documentation_url)). How should we change this? Maybe a good idea to change to strtr('Link check for %url is disabled.', array('%url' => $documentation_url)) - not sure if this keeps the string out of the POTX eyes...

boombatower’s picture

Status: Needs work » Postponed

This has been postponed til after freeze.

sun’s picture

Status: Postponed » Active
boombatower’s picture

I will attempt this using the pgp parser shortly.

boombatower’s picture

Based on drupal_web_test_case.php I have found the following assertion pattern:

Format: message

assertCacheExists
assertCacheRemoved


Format: message, group

pass
fail
error


Format: p, message, group

assert
assert*


Format: p1, p2, message, group

assertEqual
assertNotEqual
assertIdentical
assertNotIdentical
assertLink
assertLinkByHref
assertFieldByXPath
assertNoFieldByXPath
assertFieldByName
assertNoFieldByName
assertFieldById
assertNoFieldById
assertOptionSelected
assertNoOptionSelected
assertMail

assertPathMatch
assertNormalized
assertNoNormalized
assertSessionIds
assertSameLink
assertFilePermissions
assertDirectoryPermissions
assertFileHookCalled

Format: p1, p2, p3, p4, message, group

assertError


Ignore:

assertFieldSettings
assertNodeAccess
assertFailedLogin
assertTableCount
assertModules
assertLogMessage
assertFieldValues
assertCommentOrder
assertNothing
assertModuleList
assertCacheExists
assertSessionCookie
assertSessionEmpty
assertFileUnchanged
assertDifferentFile
assertSameFile
assertFileHooksCalled
assertTags
assertToolkitOperationsCalled
assertErrorMessage
assertNoErrorMessage
assertUrlOutboundAlter
assertUrlInboundAlter
assertPaths
assertReversePaths
assertComponents
assertWeights


Special:

assertAssertion

I have a coder_upgrade routine written and will be testing shortly. I will then review and provide patch.
development.module:

// $Id$

/**
 * Implements hook_upgrade_info().
 */
function development_upgrade_info() {
drupal_set_time_limit(0);
  $upgrade = array(
    'title' => t('SimpleTest remove t() from assert message, test getInfo(), etc (parser routines)'),
    'link' => 'http://drupal.org/node/500866',
  );
  return array('development' => $upgrade);
}

development.upgrade:


/**
 * Implements hook_upgrade_file_alter().
 *
 * Upgrades calls to class methods using grammar parser.
 *
 * @param PGPReader $reader
 *   The object containing the grammar statements of the file to convert.
 */
function development_upgrade_file_alter(&$reader) {
  $items = &$reader->getFunctionCalls();
  foreach ($items as &$item) {
    if (!isset($item) || !is_object($item) || !is_a($item, 'PGPFunctionCall') || $item->type != T_FUNCTION_CALL) {
      // The reference could have been changed in another routine so that it
      // no longer refers to an ojbect.
      continue;
    }

    if (is_a($item->name, 'PGPOperand') && $item->name->findNode('value') == '$this') {
      $name = substr($item->name->toString(), 7); // Strip off '$this->'.
      development_convert_asserts($item, $reader, $name);
    }
  }
}

/**
* Implements hook_upgrade_call_alter().
*/
function development_convert_asserts(&$item, &$reader, &$name) {
  $ignore = array(
    'assertFieldSettings',
    'assertNodeAccess',
    'assertFailedLogin',
    'assertTableCount',
    'assertModules',
    'assertLogMessage',
    'assertFieldValues',
    'assertCommentOrder',
    'assertNothing',
    'assertModuleList',
    'assertCacheExists',
    'assertSessionCookie',
    'assertSessionEmpty',
    'assertFileUnchanged',
    'assertDifferentFile',
    'assertSameFile',
    'assertFileHooksCalled',
    'assertTags',
    'assertToolkitOperationsCalled',
    'assertErrorMessage',
    'assertNoErrorMessage',
    'assertUrlOutboundAlter',
    'assertUrlInboundAlter',
    'assertPaths',
    'assertReversePaths',
    'assertComponents',
    'assertWeights',
  );

  $zero_single = array(
    'assertCacheExists',
    'assertCacheRemoved',
    'assertAssertion',
  );

  $zero_normal = array(
    'pass',
    'fail',
    'error',
  );

  // All assert* not otherwise accounted for: $one.

  $two = array(
    'assertEqual',
    'assertNotEqual',
    'assertIdentical',
    'assertNotIdentical',
    'assertLink',
    'assertLinkByHref',
    'assertFieldByXPath',
    'assertNoFieldByXPath',
    'assertFieldByName',
    'assertNoFieldByName',
    'assertFieldById',
    'assertNoFieldById',
    'assertOptionSelected',
    'assertNoOptionSelected',
    'assertMail',

    // None DrupalTestCase assertions.
    'assertPathMatch',
    'assertNormalized',
    'assertNoNormalized',
    'assertSessionIds',
    'assertSameLink',
    'assertFilePermissions',
    'assertDirectoryPermissions',
    'assertFileHookCalled',
  );

  $four = array(
    'assertError',
  );

  // Function name.
//  $name = $item->name['value'];

  // Halt processing if call is to be ignored.
  if (in_array($name, $ignore)) {
    return;
  }

  // Determine the assertion format.
  if (in_array($name, $zero_single)) {
    // Format: message.
    $params = array(0);
  }
  elseif (in_array($name, $zero_normal)) {
    // Format: message, group.
    $params = array(0, 1);
  }
  elseif (in_array($name, $two)) {
    // Format: p1, p2, message, group.
    $params = array(2, 3);
  }
  elseif (in_array($name, $four)) {
    // Format: p1, p2, p3, p4, message, group.
    $params = array(4, 5);
  }
  elseif (strpos($name, 'assert') === 0) {
    // Format: p1, message, group.
    $params = array(1, 2);
  }

  // Check if the function call is a recognized assertion.
  if (!empty($params)) {
    // Cycle through the parameter indexes to check, based on the assertion
    // format, and run the message extraction process.
    foreach ($params as $param) {
      development_extract_message($item, $param);
    }
  }
}

/**
* Check parameter at index for a wrapping t() function and remove if present.
*
* @param $item
*   PGP function call object.
* @param $index
*   Index of the parameter to check.
*/
function development_extract_message($item, $index) {
  if ($parameter = $item->getParameter($index)) {
    $operand = $parameter->getElement();
    if (is_a($operand, 'PGPFunctionCall') && is_array($operand->name) && $operand->name['value'] == 't') {
      if ($operand->parameters->count() > 1) {
        $operand->name['value'] = 'strtr';
      }
      else {
        $message = $operand->getParameter();
        $item->setParameter($index, $message);
      }
    }
  }
}

boombatower’s picture

Attempting to find all the other "custom" assertions defined outside DWTC. Any that deviate from the default case will need to have special cases added to script.

grep -nR --exclude-dir=CVS "n assert" .
/modules/menu/menu.test:576:    // Change default parent item to Navigation menu, so we can assert more                                                                         
./modules/file/tests/file.test:144:  function assertFileExists($file, $message = NULL) {
./modules/file/tests/file.test:152:  function assertFileEntryExists($file, $message = NULL) {
./modules/file/tests/file.test:162:  function assertFileNotExists($file, $message = NULL) {
./modules/file/tests/file.test:170:  function assertFileEntryNotExists($file, $message) {
./modules/file/tests/file.test:179:  function assertFileIsPermanent($file, $message = NULL) {
./modules/file/tests/file.test:560:  function assertPathMatch($expected_path, $actual_path, $message) {
./modules/field_ui/field_ui.test:155:  function assertFieldSettings($bundle, $field_name, $string = 'dummy test string', $entity_type = 'node') {
./modules/node/node.test:777:  function assertNodeAccess($ops, $node, $account) {
./modules/filter/filter.test:1090:  function assertNormalized($haystack, $needle, $message = '', $group = 'Other') {
./modules/filter/filter.test:1114:  function assertNoNormalized($haystack, $needle, $message = '', $group = 'Other') {
./modules/user/user.test:297:  function assertFailedLogin($account, $flood_trigger = NULL) {
./modules/system/system.test:26:  function assertTableCount($base_table, $count = TRUE) {
./modules/system/system.test:43:  function assertModules(array $modules, $enabled) {
./modules/system/system.test:77:  function assertLogMessage($type, $message, $variables = array(), $severity = WATCHDOG_NOTICE, $link = '') {
./modules/dblog/dblog.test:545:  protected function assertLogMessage($log_message, $message) {
./modules/field/tests/field.test:60:  function assertFieldValues($entity, $field_name, $langcode, $expected_values, $column = 'value') {
./modules/comment/comment.test:757:  function assertCommentOrder(array $comments, array $expected_order) {
./modules/simpletest/simpletest.test:119:    // Call an assert function specific to that class.                                                                                  
./modules/simpletest/simpletest.test:131:  function assertNothing() {
./modules/simpletest/simpletest.test:177:   * Assert that an assertion with the specified values is displayed                                                                    
./modules/simpletest/simpletest.test:187:  function assertAssertion($message, $type, $status, $file, $function) {
./modules/simpletest/tests/module.test:78:  protected function assertModuleList(Array $expected_values, $condition) {
./modules/simpletest/tests/cache.test:43:  protected function assertCacheExists($message, $var = NULL, $cid = NULL, $bin = NULL) {
./modules/simpletest/tests/cache.test:67:  function assertCacheRemoved($message, $cid = NULL, $bin = NULL) {
./modules/simpletest/tests/session.test:204:  function assertSessionCookie($sent) {
./modules/simpletest/tests/session.test:216:  function assertSessionEmpty($empty) {
./modules/simpletest/tests/session.test:373:  protected function assertSessionIds($sid, $ssid, $assertion_text) {
./modules/simpletest/tests/menu.test:481:  protected function assertSameLink($link1, $link2, $message = '') {
./modules/simpletest/tests/file.test:60:  function assertFileUnchanged($before, $after) {
./modules/simpletest/tests/file.test:78:  function assertDifferentFile($file1, $file2) {
./modules/simpletest/tests/file.test:91:  function assertSameFile($file1, $file2) {
./modules/simpletest/tests/file.test:106:  function assertFilePermissions($filepath, $expected_mode, $message = NULL) {
./modules/simpletest/tests/file.test:128:  function assertDirectoryPermissions($directory, $expected_mode, $message = NULL) {
./modules/simpletest/tests/file.test:223:  function assertFileHooksCalled($expected) {
./modules/simpletest/tests/file.test:256:  function assertFileHookCalled($hook, $expected_count = 1, $message = NULL) {
./modules/simpletest/tests/batch.test:151:  function assertBatchMessages($texts, $message) {
./modules/simpletest/tests/common.test:480:  function assertTags($tags) {
./modules/simpletest/tests/common.test:1622:  function assertError($error, $group, $function, $file, $message = NULL) {
./modules/simpletest/tests/image.test:46:  function assertToolkitOperationsCalled(array $expected) {
./modules/simpletest/tests/error.test:107:  function assertErrorMessage(array $error) {
./modules/simpletest/tests/error.test:115:  function assertNoErrorMessage(array $error) {
./modules/simpletest/tests/path.test:222:  protected function assertUrlOutboundAlter($original, $final) {
./modules/simpletest/tests/path.test:241:  protected function assertUrlInboundAlter($original, $final) {
./modules/simpletest/tests/graph.test:112:  function assertPaths($graph, $expected_paths) {
./modules/simpletest/tests/graph.test:130:  function assertReversePaths($graph, $expected_reverse_paths) {
./modules/simpletest/tests/graph.test:147:  function assertComponents($graph, $expected_components) {
./modules/simpletest/tests/graph.test:168:  function assertWeights($graph, $expected_orders) {
boombatower’s picture

Updated #42 based on grep in #43.

boombatower’s picture

Status: Active » Needs review
FileSize
1.09 MB

/me crosses fingers

Status: Needs review » Needs work

The last submitted patch, 500866-remove-t.patch, failed testing.

boombatower’s picture

Status: Needs work » Needs review
FileSize
1.09 MB

Fixed what appears to be pgp issue with "instanceof".

Status: Needs review » Needs work

The last submitted patch, 500866-remove-t.patch, failed testing.

boombatower’s picture

Status: Needs work » Needs review
FileSize
1.09 MB

PGP bugs fixed...lets see how this works.

Status: Needs review » Needs work

The last submitted patch, 500866-remove-t.patch, failed testing.

boombatower’s picture

boombatower’s picture

Status: Needs review » Needs work
boombatower’s picture

Status: Needs work » Needs review
FileSize
1.06 MB

PGP issues have been fixed.

3274 added, 3271 removed!

boombatower’s picture

Only remaining annoyance is:

-    if ($contact !== TRUE) { // If true then attempting to find error message.
+    if ($contact !== TRUE) {
+ // If true then attempting to find error message.

Which isn't syntax obviously.

boombatower’s picture

A lot of syntax fixes and poor spacing (like 3 spaces!?), dot issues, and failsauce like:

-      'description' => 'Perform various tests with cron trigger.' ,

Currently investigating some encoding issues with common.test.

boombatower’s picture

Summed comment formating issues: #726054: Standardize/Correct comment formating, it seems to also add an extra trailing space with certain statements, but solotandem tells me he has that one fixed.

Otherwise this is great to see it fixing all the formating oddballs.

boombatower’s picture

FileSize
1.05 MB

Trailing white space issue fixed, other two instances of bad comment formatting fixed, manually reviewed (scanned). Overally it looks good, and bot likes it.

Status: Needs review » Needs work

The last submitted patch, 500866-remove-t.patch, failed testing.

boombatower’s picture

Status: Needs work » Needs review
FileSize
1.05 MB

Since trailing whitespace is removed by pgp in latest version it screws up an assertEqual().

andypost’s picture

Confirm that patch passes all tests localy

sun’s picture

+++ modules/comment/comment.test	25 Feb 2010 23:10:50 -0000
@@ -768,7 +768,7 @@
-    return $this->assertIdentical($expected_cids, $result_order, t('Comment order: expected @expected, returned @returned.', array('@expected' => implode(',', $expected_cids), '@returned' => implode(',', $result_order))));
+    return $this->assertIdentical($expected_cids, $result_order, strtr('Comment order: expected @expected, returned @returned.', array('@expected' => implode(',', $expected_cids), '@returned' => implode(',', $result_order))));

@@ -828,7 +828,7 @@
-      $this->assertIdentical($expected_page, $returned_page, t('Flat mode, @new replies: expected page @expected, returned page @returned.', array('@new' => $new_replies, '@expected' => $expected_page, '@returned' => $returned_page)));
+      $this->assertIdentical($expected_page, $returned_page, strtr('Flat mode, @new replies: expected page @expected, returned page @returned.', array('@new' => $new_replies, '@expected' => $expected_page, '@returned' => $returned_page)));

So what about stuff like that? That's not the same.

Powered by Dreditor.

boombatower’s picture

How not?

$new_replies = 'NEW!';
$expected_page = 'NEW!';
$returned_page = 'NEW!';
echo strtr('Flat mode, @new replies: expected page @expected, returned page @returned.', 
  array('@new' => $new_replies, '@expected' => $expected_page, '@returned' => $returned_page));

Prints: Flat mode, NEW! replies: expected page NEW!, returned page NEW!.

andypost’s picture

@boombatower t() is doing check_plain() for @ and drupal_placeholder for %, I think that you need some function to make it (st() parsed by potx too)

boombatower’s picture

Having the italics in the output message is really of little to no importance in the simpletest assertion messages. What do you mean by the last bit, "st() parsed by potx too"? Is strtr parsed by potx?

andypost’s picture

I mean http://api.drupal.org/api/function/st/7
Strings passed to st() are extracted to be translated too!

Agree about placeholders, also I think about check_plain() - it's required because variables mostly randomName() so could lead to breaking output HTML

webchick’s picture

Status: Needs review » Needs work

strtr() is just a PHP function, so it's not parsed by potx.

However, as a test author, that's really annoying to have to cludge together this weird strtr() string just to avoid calling t().

These should ideally be switched to:

$this->assertIdentical($expected_page, $returned_page, "Flat mode, $new_replies replies: expected page $expected_page, returned page $returned_page");

I'm not sure if that's possible with PHP Grammar Parser (which I refuse to call PGP because that's just an encryption type :P).

sun’s picture

It's not only about breaking your layout. It's about outputting HTML.

$string = '<script type="text/javascript">alert("BAM!");</script>';
$this->assertEqual($expected, $returned, "Proper output: $string");

Two options:

a) Don't remove t() for messages using placeholders.

b) Introduce a t()-replacement helper function for testing. t() stands for "translate". s() for "string". Optionally make t() invoke s(). Might be helpful in a lot of other places.

webchick’s picture

Meh. Not crazy on "yet another silly one-or-two letter function name for dealing with strings", especially during API freeze, so b) is out for me.

a) makes sense, but then we create yet more inconsistency where "sometimes" you use t() around assertions and other times you don't.

....which makes me wonder why we bother doing all this in the first place. ;P If we just used t() everywhere, and adjusted our potx extractors to not parse .test files, we wouldn't have to teach our test writers/reviewers any special tricks.

sun’s picture

If we just used t() everywhere, and adjusted our potx extractors to not parse .test files

I originally wanted to suggest this, too. But then I realized that a single test run will add 1,423,598,172 stupid strings to {locale_source} on your site. In turn, this would mean that you cannot run tests on any site where data matters. Bad.

boombatower’s picture

I really don't see the need to for test to be dumping such data as HTML and what not. My instinct was to do "$var stuff" or $var . " stuff", but felt the strtr was a closer match. I can see about changing, but I want agreement on it. Personally I am fine with dropping strtr, but keeping t() around is just bad. In all tests I write (in contrib and what not) I no longer use t() and create string using normal appending process. Creating yet another oddness is just not a good idea.

webchick’s picture

Thinking about it more, I'm actually not sure #67 is that big of a deal, really. As a test author it's your problem to call check_plain(), check_markup(), etc. accordingly in places where you're outputting dangerous strings. Else we could try making the $message variable passed into assert() check_plain()ed and see how much stuff breaks.

In terms of what to replace strtr() with, "Blah dee blah $variable" seems the most natural to me.

andypost’s picture

Same way we have http://api.drupal.org/api/function/_dblog_format_message/7 which put a log of garbage into {locale_source}

I think it's a good idea to have some default implementation for printing function with escaping, so t() could use it and st() too.

"for $bar baz" is good for reading but fail in security!

sun’s picture

Broken tags.

boombatower’s picture

After reading the comments over again, I think we should stick to "Text $var" instead of something else. These are tests the messages are purely for debug purposes and shouldn't be outputting HTML or the like, and if they do? so what? these are developer tools and messages...if we can't trust the developer there isn't much we can prevent them from doing.

I'll revisit the script and see if I can get these merged into a string. I believe I started on it, but stopped due to comments. If I can get a confirmation then I'll go ahead and update the script and role a patch.

boombatower’s picture

This was confirmed by webchick and Dries so I'll begin updating the script.

boombatower’s picture

Need to figure out why script crashes on filter.test and error.test, but I went ahead and created a place where I can work on code. Aside from the crash the code does what is required.

http://github.com/boombatower/drupal-dev/tree/500866

solotandem’s picture

FileSize
1.23 MB

I updated the code in the github repository and attached a new patch.

The upgrade routine was not dealing with 3 test files (error, form, and filter) that had calls to t() where the $args replacement parameter was a variable as opposed to an inline array. For example, from error.test:

t('Found %type in error page.', $error_pdo_exception)

All other calls to t() (to be changed by this patch) have an inline array of replacement values, like:

t("Found '!message' in error page.", array('!message' => $error_details))

To handle the first case, the upgrade routine searches for the most recent assignment to the replacement variable using the Grammar Parser API. From this statement object, the array keys can be extracted.

There are 2 cases of changes in the attached patch:
1) with an inline array of replacement values, each key in the t() message string is replaced by the corresponding value in the replacement array.
2) with a variable assigned elsewhere, each key in the t() message string is replaced by the corresponding key in the variable, e.g. $variable[$key]. To see an example of this, search for error.test in the patch file.

solotandem’s picture

Status: Needs work » Needs review

Change status.

Status: Needs review » Needs work

The last submitted patch, 500866-remove-t.patch, failed testing.

solotandem’s picture

Status: Needs work » Needs review
FileSize
1.23 MB

Oops. CVS diff from inside the modules dir.

Status: Needs review » Needs work

The last submitted patch, 500866-remove-t.patch, failed testing.

boombatower’s picture

Status: Needs work » Needs review
FileSize
1.23 MB

Curious.

Status: Needs review » Needs work

The last submitted patch, 500866-remove-t.patch, failed testing.

boombatower’s picture

Status: Needs work » Needs review
FileSize
99.89 KB
boombatower’s picture

Status: Needs review » Needs work

hmm

boombatower’s picture

Status: Needs work » Needs review
FileSize
256.75 KB

solotandem updated script for API changes and we tweaked it to removed trailing or starting . '' or '' .

boombatower’s picture

Status: Needs review » Needs work

Arg, the patch is missing quite a few.

boombatower’s picture

Status: Needs work » Needs review
FileSize
1.26 MB

Previous patches involved silly mistakes....this one looks good.

solotandem’s picture

Status: Needs review » Reviewed & tested by the community

Patch is obviously large, so not likely to go over in entirety with fine tooth comb. But a manual review of the 2 test cases indicates all looks well.

boombatower’s picture

I also review the first 1000 lines and spot check a lot more.

boombatower’s picture

Up-to-date version of the code used to generate patch can be found at http://github.com/boombatower/drupal-dev/tree/500866.

boombatower’s picture

More accurate title...we can do followup for getInfo and what not if we choose to.

andypost’s picture

Title: Simpletest: remove t() from assert message » Simpletest: remove t() from assert message, test getInfo(), etc

So now we need commiters to apply this patch and re-roll all patches that contains tests with t()

boombatower’s picture

Title: Simpletest: remove t() from assert message, test getInfo(), etc » Simpletest: remove t() from assert message

cross post....

also note simply apply them and run teh script.

webchick’s picture

Title: Simpletest: remove t() from assert message, test getInfo(), etc » Simpletest: remove t() from assert message
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs documentation

Ok. This is something we agreed to do in Drupalcon SF. And although it's incredibly, stupidly late, committing it is necessary so that translators don't end up with oodles and oodles of useless extra strings to translate.

Committed to HEAD. Make sure this is reflected in the SimpleTest documentation, and the module upgrade guide (along with how devs can modify their own tests using the script you have here).

Damien Tournoud’s picture

Category: task » bug
Priority: Normal » Critical

PLEASE REVERT.

This patch removed HTML encoding in *a lot* of places (ie. calls to check_plain()). t() automatically does that for you, reverting to string concatenation feels really wrong.

What we need here is a non-translating version of t(). Let's call it nt(). It does what t() does in terms of placeholder replacement and encoding, but (1) doesn't call locale() and (2) doesn't get extracted by potx.

This would have reduced the size and complexity of that patch by a ton, and is really useful for other stuff (like development shops, like us, that sometimes develop custom modules using non-English strings in code, don't want to lose placeholder replacement and want to keep track of strings that might be translated one day).

sun’s picture

Issue tags: -Needs documentation

Agreed with Damien. And, hm. The more I've tried to not use t() in assertion messages in code recently, the more I was in the need for such a replacement t() function. However, the more I thought about a replacement t() function, the more often I asked myself whether that replacement t() function wouldn't be the same as t() for >99% of all cases, since t() was and still is designed to be very performant for the English-only use-case already. Additionally, proper usage of t() is very well known already.

Originally, I concluded above:

If we just used t() everywhere, and adjusted our potx extractors to not parse .test files

I originally wanted to suggest this, too. But then I realized that a single test run will add 1,423,598,172 stupid strings to {locale_source} on your site. In turn, this would mean that you cannot run tests on any site where data matters. Bad.

But if that - i.e., the addition of yet unknown locale source strings in the rare case of running tests on a production database of a Drupal site having multiple languages enabled -- if that is really the only issue with using t() in tests and making potx skip .test files, then I think we could surely tweak t() resp. locale() to never pollute {locale_source} when running tests. Similar to how we've tweaked other bare essential core functions elsewhere for testing.

webchick’s picture

Category: bug » task
Priority: Critical » Normal

Ok, at any rate, this still needs additional discussion. Reverted.

andypost’s picture

If we run tests on dev server how it's possible to sync strings with production?

making potx skip .test files

Also test modules and probably this helps #779204: Move simpletest/tests/*.test files into system/tests/*.test

never pollute {locale_source} when running tests

This applies only to DB of site that performs tests

Damien Tournoud’s picture

Status: Needs work » Needs review
FileSize
1.47 KB

It starts here. I'm sure changing the correct t() to nt() would not be hard with coder upgrade.

sun’s picture

Status: Needs review » Needs work

Yes, the scenario I'm describing is only possible by running DrupalUnitTestCases, or alternatively, within the context of something along the lines of #666956: Provide DrupalCloneTestCase for testing pre-configured drupal sites

sun’s picture

That's the same as:

function nt($string, array $args = array(), array $options = array()) {
  $options['langcode'] = 'en';
  return t($string, $args, $options);
}

No?

Damien Tournoud’s picture

No, that's not. We need to skip the whole custom string logic, because it doesn't apply here. Duplicating the (tiny) placeholder replacement logic feels better then bloating t() with new corner-cases.

drewish’s picture

at the risk of bikeshedding would p() for placeholder be better than nt() for not-translated? agree that we need another function for doing check_plain()ed replacement.

Damien Tournoud’s picture

nt() or p(), I can buy either.

webchick’s picture

Not p(). Has no correlation to the existing t() function and we already use st() for a "special" t().

Dave Reid’s picture

nt() makes sense to me since "not translated" is (almost) the opposite of "translate" (if you don't count verb tense)

boombatower’s picture

#101: Also note that a much improved version of that patch (I'll comment on issue as well) is maintained in contrib SimpleTest 7.x-2.x and Examiner.com makes heavy use of it.

Another thought....why do we have HTML in assertion messages? Just as Damien argued in IRC we should be consistent with PHP and since assertion messages mirror (and in some cases are a shell for) exceptions/errors and PHP uses plain text messages we should as well. As such encoding HTML entities should be a non-issue, but if we really want to be sure...why not just throw a check_plain() in $this->assert()...I find the whole t('...', array(...)) very bulky compared to 'foo ' . $bar . 'sf' especially when these strings are simply debug information for tests.

If we really really have to go with a t() variant then my vote is on p()...simply because it seems arbitrary and one less character to type over and over, but obviously not a big deal in the end. Considering we never plan to translate these strings the use-case Damien mentioned in IRC about just switch nt|p() to t() if you want to end up translating a site and what not...really doesn't apply in our case so I'd much prefer raw string concatenation.

Either way I am quite annoyed that this all comes out after solotandem and myself wrote up the script (after receiving no further discussion and agreement) instead of before...big waste of time if we don't end up using it (which I'm also against as stated above).

webchick’s picture

Version: 7.x-dev » 8.x-dev

k, seriously, screw this. we'll deal with it in D8.

pillarsdotnet’s picture

Why don't we start by removing all the t() calls that don't do any string replacement?

I used the following commands to generate a patch:

git checkout 7.x
perl -pi -e "s|\\\$this->assert(.*), t\\((['\"])(.*)(['\"])\\)\\);|\\\$this->assert\\1, \\2\\3\\4);|" $(egrep -rl '\$this->assert.*, t\(.*\)\);' modules)
git diff --no-prefix > ~/Patches/d7/remove-unnecessary-t-from-assert.patch
boombatower’s picture

Version: 8.x-dev » 7.x-dev
Status: Needs work » Needs review

The comment about an alternative t() function is just pie in the sky...this should have gone in as it was patched...but after so much crap and people who seemingly wanted to derail this I was exhausted as happens a lot of with core.

If we can move past that stuff...we can re-run the script and commit this.

pillarsdotnet’s picture

Patch no longer applies. Re-rolled.

pillarsdotnet’s picture

Trying again without the "--no-prefix" option.

boombatower’s picture

Please just rerun the script or don't bother. No need for this issue to drag into multiple stages...lets do it or don't.

pillarsdotnet’s picture

All tests passed this time. It appears that patches created with the "--no-prefix" option are now rejected by the testbot.

pillarsdotnet’s picture

#88: 500866-remove-t.patch queued for re-testing.

pillarsdotnet’s picture

Patch in #88 no longer applies. Could boombatower either re-run the script or explain to a dummy like me how to re-run it?

boombatower’s picture

Install this module (http://github.com/boombatower/drupal-dev) on your d7 site, install coder_upgrade (usually best to use dev) from (http://drupal.org/project/coder) and then run an "upgrade" on the entire core with the routine defined in the "development.upgrade" file. From the .module file "SimpleTest remove t() from assert message, test getInfo(), etc (parser routines)" should be displayed in coder upgrade interface.

TR’s picture

Issue tags: +Needs documentation

Somewhere along the line the Needs Documentation tag that was put on by webchick in #29 got lost.

The part that needs documentation is the removal of t() from the return values of getInfo(), which was committed in #29. Searching all the SimpleTest documentation on drupal.org reveals only one brief mention, in a tutorial, about what to put in getInfo(). Because this function is not inherited from DrupalWebTestCase or one of its parents, and is not defined by an interface, documentation of the function signature or return values doesn't show up on api.drupal.org (can't search for it there ...) or on drupal.org. I just fixed one handbook page that had the wrong signature and still used t() in its example, but an example of getInfo() is no substitute for proper documentation. I also submitted a patch to the examples module because some of the example tests were still using t().

pillarsdotnet’s picture

After following boombatower's instructions, I consistently get the following error:

PHP Fatal error: Call to undefined method PGPOperand::getKey() in sites/all/modules/drupal-dev/development.upgrade on line 180

The getKey() method is defined for the PGPArray class, but not for the PGPList class from which the PGPOperand class is derived.

Apparently boombatower's module is not synchronized with the grammar_parser module.

(trying earlier versions of the grammar_parser codebase...)

Okay, if I checkout an earlier version of grammar_parser and then patch coder_upgrade.module to match, it runs for a slightly longer period of time before crash-and-burning.

Can boombatower please specify which commit number he is using from grammar_parser and coder projects?

boombatower’s picture

I'll take a look and see if I can't update it, obviously it's been sometime :)

solotandem’s picture

FileSize
1.44 MB

Let's try this patch.

The upgrade code (in github repository mentioned in #119, and last run in #88) needed to be tweaked for one test class, testTaxonomyUpgrade. If this passes, then I will update the repository code.

Status: Needs review » Needs work

The last submitted patch, 500866-remove-t_4.patch, failed testing.

solotandem’s picture

Status: Needs work » Needs review
FileSize
1.44 MB

Same patch except in -p1 format.

webchick’s picture

Version: 7.x-dev » 8.x-dev

This is definitely 8.x now. We'll just have to live with 7.x being in an inconsistent state. :\

solotandem’s picture

Version: 8.x-dev » 7.x-dev

The patch in #125 fails on one assertion. It would have passed except for a bug in the existing test code for testTaxonomyUpgrade. On line 159, the t() call wants a replacement for key = '%old_vid' and this key is not present in the $args array at that point in the code.

See #1097686: UpgradePathTaxonomyTestCase: replacement argument for "%old_vid" not set.

solotandem’s picture

Version: 7.x-dev » 8.x-dev

Didn't intend to change version (page loads with 7.x in post new comment settings).

pillarsdotnet’s picture

Issue tags: -Needs documentation

#125: 500866-remove-t_5.patch queued for re-testing.

Since the offending line does not exist in 8.x, setting the issue version to 8.x should allow the test to pass.

Status: Needs review » Needs work
Issue tags: +Needs documentation

The last submitted patch, 500866-remove-t_5.patch, failed testing.

pillarsdotnet’s picture

Status: Needs work » Needs review
FileSize
1.72 MB

Re-rolled against fresh 8.x checkout.

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-131.patch, failed testing.

pillarsdotnet’s picture

Status: Needs work » Needs review
FileSize
1.72 MB

Fixed.

pillarsdotnet’s picture

Trying again...

pillarsdotnet’s picture

Found a bunch more in drupal_web_test_case.php

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-135.patch, failed testing.

pillarsdotnet’s picture

And again...

pillarsdotnet’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-137.patch, failed testing.

pillarsdotnet’s picture

Status: Needs work » Needs review
FileSize
1.75 MB

And again...

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-140.patch, failed testing.

pillarsdotnet’s picture

Status: Needs work » Needs review
FileSize
1.75 MB

And again...

pillarsdotnet’s picture

Issue tags: -Needs documentation
pillarsdotnet’s picture

Status: Needs review » Needs work
Issue tags: +Needs documentation

The last submitted patch, simpletest_remove_t-500866-142.patch, failed testing.

pillarsdotnet’s picture

Status: Needs work » Needs review
FileSize
1.75 MB

Re-rolled because of changes in core.

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-146.patch, failed testing.

pillarsdotnet’s picture

Assigned: boombatower » pillarsdotnet
Status: Needs work » Needs review
FileSize
1.75 MB

Apologies for the noise, but there is no way I can test this locally.

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-148.patch, failed testing.

pillarsdotnet’s picture

Status: Needs work » Needs review
FileSize
1.75 MB

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-150.patch, failed testing.

pillarsdotnet’s picture

Status: Needs work » Needs review
FileSize
1.75 MB

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-152.patch, failed testing.

pillarsdotnet’s picture

Status: Needs work » Needs review
FileSize
1.75 MB
boombatower’s picture

I must say I appreciate your persistence, once this passes I hope we can get it committed quickly.

pillarsdotnet’s picture

Status: Needs work » Needs review

Not likely, given the size of the queue. But it's easier to maintain than to start over from scratch.

EDIT: Just found a bunch more -- I had been searching for " t(" and not "(t(".

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-154.patch, failed testing.

solotandem’s picture

Status: Needs review » Needs work

@pillarsdotnet, When you write, "Just found a bunch more -- I had been searching for ' t(' and not '(t('," does this mean you are editing/creating the patch manually? Or, are you using the automated routine described in #119 and other prior comments?

pillarsdotnet’s picture

I'm editing manually. The automated routine is broken and boombatower hasn't had time to fix it yet.

(clickety...)

Only 28 more files to go.

solotandem’s picture

I updated the code in https://github.com/boombatower/drupal-dev.git back in March when I determined what was causing the failure in the taxonomy test case. (But I failed to indicate so.) Give it a try and save yourself all the tedious manual labor. Let me know if you encounter any issues.

solotandem’s picture

Status: Needs work » Needs review
FileSize
1.47 MB

A new patch created with the automated routine.

pillarsdotnet’s picture

Okay, I'll use that as a starting point, but it misses a bunch of 'em.

pillarsdotnet’s picture

Here's a partial; still 27 files to edit.

Status: Needs review » Needs work

The last submitted patch, simpletest_remove_t-500866-163.patch, failed testing.

webchick’s picture

Note: Time in this issue is much better spent editing the automator script so it catches what your grepping does. In this way, time wouldn't need to be spent constantly chasing 8.x, but could instead the script could just be run by core committers at a time when committing this is deemed least invasive to other things going on.

solotandem’s picture

Status: Needs work » Reviewed & tested by the community

@pillarsdotnet, I believe you are mistaken as to the changes to be made by the patch. Based on a comparison of your patch in #163 and mine in #161, you are removing all calls to t() in the tests. That is not the intention. Continuing to do so will continue to guarantee test failures.

Please review #5 which shows some examples and is agreed to as the desired approach by several comments thereafter.

The patch in #161 is the one to commit and, unless someone can prove otherwise, is RTBC. This patch was prepared using the methodology described in the earlier comments on this issue.

@webchick, Please commit the patch from #161.

webchick’s picture

Status: Reviewed & tested by the community » Needs review

Committing this or not is the domain of Dries; this isn't a D7 patch. Please don't mark your own patches RTBC. :)

solotandem’s picture

Assigned: pillarsdotnet » Unassigned
FileSize
1.47 MB

A new patch created with the automated routine, without changes to indention of '//' style comments.

Status: Needs review » Needs work

The last submitted patch, 500866-remove-t.patch, failed testing.

boombatower’s picture

Status: Needs work » Reviewed & tested by the community

Looks good.

Rather then continually postponing this or derailing this with pie in the sky stuff, I would appreciate it if we could get this through so we don't needlessly miss another release.

lyricnz’s picture

Agree - let's get this in (before it gets stale), and document the new standard, so we can point to it for contrib and new tests.

webchick’s picture

Also, I guess I should point out that no D8 clean-up patches / features are going to make it in at all, while the number of critical bugs exceeds 15 between D7 & D8. It's currently at 21.

Hopefully we can get some of those moved to RTBC soon.

tstoeckler’s picture

Why shouldn't this be backported to D7?

solotandem’s picture

We can all appreciate the desire to resolve critical bugs in a feature-stable code environment.

Yet, somehow a cleanup to tests would seem bifurcated from critical bugs dealing with core. In other words, what is the chance of bug in the test environment being flagged as critical? How can changes of this nature to the test environment (which is arguably distinct from the features provided by core) overlap with with and affect resolution of feature bugs?

So, again, why should committing this patch wait on critical feature bugs that have no bearing on it, nor will its commitment affect the resolution of those critical bugs (except possibly to remove a t() or two from any updated tests)?

webchick’s picture

Because this patch doesn't actually fix anything. It's a syntactical nicety that's adding consistency to .test files, and that's great, and totally on the table for 8.x (unfortunately we can't introduce it in 7.x anymore, because it would represent an API change of sorts, so we'll have to live with the inconsistency in D7).

But clean-up patches like this require re-rolls of other, more pressing issues in the queue, like major/critical bug fixes for D7 (because they must be applied to D8 first), which is actively being used in production right now. To prevent the problem we had in D7 where we got to code freeze and had 100+ critical issues to deal with and extended the release date of D7 by a year+, Dries imposed a rule regarding the number of critical bugs during his keynote at DrupaCon Chicago. If it gets > 15, then the only thing that gets committed are bug fixes until that number goes down. It's an incentive to get people to focus on the important stuff before the clean-up stuff/feature stuff, or at the very least not screw over people who are actively working on the important stuff.

See #1050616: Figure out backport workflow from Drupal 8 to Drupal 7 for a large discussion on this issue, particularly most of catch's posts.

pillarsdotnet’s picture

@#174 -- The proper issue to discuss such topics is #1050616: Figure out backport workflow from Drupal 8 to Drupal 7.

And most patches to core should be accompanied by changes to tests, although many of them don't.

catch’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: -Needs documentation +Needs backport to D7, +Needs change record

We need to discuss:

-    $this->assertRaw(t('The category %title has been added.', array('%title' => $category_1['title'])), t('The category %title has been added.', array('%title' => $category_1['title'])));
+    $this->assertRaw(t('The category %title has been added.', array('%title' => $category_1['title'])), 'The category ' . $category_1['title'] . ' has been added.');

I'm not at all convinced that's a good change, could create confusion for developers.

However I don't see why the patch in general couldn't be applied to D7, it's not an API change, just applying a pattern where one no longer existed - does not enforce that contrib modules do this.

sun’s picture

Two very closely related issues:

- #1191614: Make t() formatter available as its own function: would imply to replace t() with format_string() in test assertion messages.

- #1213510: A modern t(): might imply to merely append a method to t() calls in test assertion messages.

catch’s picture

Issue tags: -Needs change record +best practices change

Switching 'needs change notification' to 'best practices change'.

jwilson3’s picture

I'm not totally up to speed on how Drupal calculates which strings should be translated for pot-file generation, and am only coming to this thread because I was just asked to change a core patch to remove t() from some assertion messages. I'm looking to see if this is an official best practice now or what.

Without an issue summary its hard to tell if the idea *is* going to be implemented, and if I really *should* remove t() from my message or not.

Also, I haven't read all 179 comments on this issue, so not sure if this idea has been suggested and discarded already, or if its just an uninformed idea, but... throwing caution to the wind... could it make sense to just exclude *.test from the list of file types to search for translation strings? This would allow us to ignore all strings in test files, including those instances where t() is still being used for placeholder replacement.

xjm’s picture

Tagging per #180.

jwilson3’s picture

If the test files themselves should be as t() free as possible, should not the primary API drupal_web_test_case.php also follow suit? The most recent patch doesn't remove simple strings from this file. Here are some examples:

Assertion message categories:

t('Browser')
t('E-mail')
t('Other')
t('Role')

Various simple assertion messages themselves:

t('Log out')
t('Email:')
t('Parsed page successfully.')
t('Verbose message')
t('The test did not complete due to a fatal error.')
t("The test cannot be executed because it has not been set up properly.")

Various t-based string substitutions. From what I can gather looking at the most recent patch, it looks like these need to be simplified as well. E.g.:

t('User created with name %name and pass %pass', array('%name' => $edit['name'], '%pass' => $edit['pass']))
t('Failed to set field @name to @value', array('@name' => $name, '@value' => $value)

What makes this uber-confusing is the possible need to leave *some* of the simple t() strings in place in the tests files. Consider the $submit argument of the DrupalTestCase::drupalPost() method, which according to the current API, should be wrapped in t(). Hoping someone more involved on the thread can shed some light here.

webchick’s picture

Status: Needs work » Postponed (maintainer needs more info)

Can someone remind me why we want to do this again? Originally it was because we didn't want translators to have to translate these strings, which is absolutely true. However, if you do a search on localize.drupal.org for a string like 'Empty message correctly rejected during parsing' you'll see these strings already aren't coming up for translators. So this problem has already been worked around, even before Drupal 7's release.

Switching from t() to some other string mechanism means developers have to break their good habits of always wrapping user-facing input in t() in order to write tests, and have to learn a different way of handling dynamic strings like t('Created the @foo type', array('@foo' => $foo)) than they do in 99.9% of the rest of their code.

Tests already have enough barriers. Why do we want to add more?

xjm’s picture

Well, there's really no reason to add t() to the assertion message string. That's just needless overhead.

Output from test themes and modules is a different case and I'm on the fence about that. However, sun's point has been that it helps us test only the things being tested by decoupling what's being tested from all the other implicit stuff (translation in this case).

Edit: The example catch cites in #177 should probably use format_string() rather than a concatenation.

Edit: jhodgdon and I recently documented the current practice at http://drupal.org/simpletest-tutorial-drupal7#t.

boombatower’s picture

It just 30k needless semi-expensive function calls.

yched’s picture

We have format_string() now - looks like a perfect match for those assert messages.

Only drag is the func name feels too verbose - I'd rename to s(), personnally.
s() - don't translate,
t() - translate,
easy :-)

webchick’s picture

Status: Postponed (maintainer needs more info) » Needs work

Thanks. "Performance" seems like a reasonable reason, as does using format_string(). The issue summary could really use an update.

xjm’s picture

I'll update the handbook page to remove the bit about load for translators, since you've indicated that's already fixed.

hass’s picture

+1 for renaming format_string to s() in D8. :-)

Jose Reyero’s picture

While renaming format_string() to s() seems a good idea to me, we'd need to move on with this either way. Replacing 'format_string' by 's' will be a quick and straight forward one anyway so we can discuss that one in parallel since that is a different issue to this one.

But in the meanwhile tons of tests are being written using lots of t() for Drupal 8 and this patch would become bigger and bigger.
On top of that, has anyone noticed that Drupal 8 unit tests are failing if you run them locally from a site with Locale module enabled? (yes, because of translating assert messages).

ZenDoodles’s picture

FileSize
1.29 MB

xjm suggested limiting the scope to plain strings only, with a follow up for complex strings: #1681890: Use format_string() instead of t() for assertion message text

xjm also asked me to post the bash script I wrote because it was faster than trying to figure out how to fix the one above to only find the plain strings:

for file in `grep -rl 'assert[A-Za-z]*(.* t([^)]*));$' core/modules/`
do
  # No need to check, we only have files fitting the criteria from grep.
  mv $file $file.tmp
  sed  's#\(assert[A-Za-z]*(.* \)t(\([^)]*)\));#\1\2;#g' $file.tmp > $file
  rm $file.tmp
  echo Fixed $file
done

I know it's tricksy with the end paren bits, but it IS just a one time script I wasn't planning to share. :)

I found the getInfo() bits with: grep -rA4 "function getInfo(." Projects/core/modules/*/lib/Drupal/*/Tests/ | grep "'name' => t("
since there were only 6, I just manually fixed 'em.

Let's see what the bot has to say...

ZenDoodles’s picture

Status: Needs work » Needs review
Tor Arne Thune’s picture

Great start, indeed :)
I noticed that the space before t() was also removed, so that there is no space between parameters.
Example:
$this->assertRaw($base_theme_project_link,'Link to the Update test base theme project appears.');

Status: Needs review » Needs work

The last submitted patch, assert_t-500866-191.patch, failed testing.

tim.plunkett’s picture

Those failures are from incorrectly removing t() when it should be switched to format_string().

Which makes me think, would it be easier to do #1681890: Use format_string() instead of t() for assertion message text first?

boombatower’s picture

Solotandem is in irc and can be asked for details on changing the script. Better then chasing all the special cases and formatting issues from the shell script since reg ex is not suited to this task.

ZenDoodles’s picture

Assigned: Unassigned » ZenDoodles

@Tor Arne Thune and @timplunkett You're absolutely right, I thought I had corrected for those. Let me be sure I got the right patch and if not fix it.

@boomatower I don't understand how regex via preg_replace w/ PCRE limitations is better than regex via bash/sed. The point here was we don't want all the special cases for this patch. Only straight ahead t() on the last parameter of an assertion. I think the php script will still be useful for #1681890: Use format_string() instead of t() for assertion message text.

boombatower’s picture

The script used by solotandem and I is not a bunch of regex...it uses a parser to parse/change/writeout code. Use whatever you like (just suggested the parser since you seem to be having issues with regex hitting the case correctly) as those of us who have worked on this are long burned out from repeated shedding.

sun’s picture

Status: Needs work » Needs review
FileSize
1.29 MB
185 bytes

I've fixed the script.

However, unless this blocks something, then I'd highly recommend to defer the commit until after feature freeze. Committing this patch will cause quite some hazard.

tim.plunkett’s picture

Status: Needs review » Needs work

These are what I was taking about in #195, they should be format_string.

+++ b/core/modules/filter/lib/Drupal/filter/Tests/FilterCrudTest.phpundefined
@@ -88,17 +88,17 @@ class FilterCrudTest extends WebTestBase {
-    $this->assertEqual($db_format->format, $format->format, t('Database: Proper format id for text format %format.', $t_args));
-    $this->assertEqual($db_format->name, $format->name, t('Database: Proper title for text format %format.', $t_args));
-    $this->assertEqual($db_format->cache, $format->cache, t('Database: Proper cache indicator for text format %format.', $t_args));
-    $this->assertEqual($db_format->weight, $format->weight, t('Database: Proper weight for text format %format.', $t_args));
+    $this->assertEqual($db_format->format, $format->format, 'Database: Proper format id for text format %format.', $t_args);
+    $this->assertEqual($db_format->name, $format->name, 'Database: Proper title for text format %format.', $t_args);
+    $this->assertEqual($db_format->cache, $format->cache, 'Database: Proper cache indicator for text format %format.', $t_args);
+    $this->assertEqual($db_format->weight, $format->weight, 'Database: Proper weight for text format %format.', $t_args);
 
     // Verify filter_format_load().
     $filter_format = filter_format_load($format->format);
-    $this->assertEqual($filter_format->format, $format->format, t('filter_format_load: Proper format id for text format %format.', $t_args));
-    $this->assertEqual($filter_format->name, $format->name, t('filter_format_load: Proper title for text format %format.', $t_args));
-    $this->assertEqual($filter_format->cache, $format->cache, t('filter_format_load: Proper cache indicator for text format %format.', $t_args));
-    $this->assertEqual($filter_format->weight, $format->weight, t('filter_format_load: Proper weight for text format %format.', $t_args));
+    $this->assertEqual($filter_format->format, $format->format, 'filter_format_load: Proper format id for text format %format.', $t_args);
+    $this->assertEqual($filter_format->name, $format->name, 'filter_format_load: Proper title for text format %format.', $t_args);
+    $this->assertEqual($filter_format->cache, $format->cache, 'filter_format_load: Proper cache indicator for text format %format.', $t_args);
+    $this->assertEqual($filter_format->weight, $format->weight, 'filter_format_load: Proper weight for text format %format.', $t_args);
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleCommentLanguageTest.phpundefined
@@ -101,7 +101,7 @@ class LocaleCommentLanguageTest extends WebTestBase {
-        $this->assertEqual($comment->langcode, $langcode, t('The comment posted with content language %langcode and belonging to the node with language %node_language has language %comment_language', $args));
+        $this->assertEqual($comment->langcode, $langcode, 'The comment posted with content language %langcode and belonging to the node with language %node_language has language %comment_language', $args);
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleJavascriptTranslation.phpundefined
@@ -89,12 +89,12 @@ class LocaleJavascriptTranslation extends WebTestBase {
-      $this->assertTrue(isset($source_strings[$str]), t("Found source string: %source", $args));
+      $this->assertTrue(isset($source_strings[$str]), "Found source string: %source", $args);
 
       // Make sure that the proper context was matched.
-      $this->assertTrue(isset($source_strings[$str]) && $source_strings[$str] === $context, strlen($context) > 0 ? t("Context for %source is %context", $args) : t("Context for %source is blank", $args));
+      $this->assertTrue(isset($source_strings[$str]) && $source_strings[$str] === $context, strlen($context) > 0 ? t("Context for %source is %context", $args) : "Context for %source is blank", $args);
+++ b/core/modules/system/lib/Drupal/system/Tests/Form/ProgrammaticTest.phpundefined
@@ -84,7 +84,7 @@ class ProgrammaticTest extends WebTestBase {
-    $this->assertTrue($valid_input == $valid_form, t('Input values: %values<br/>Validation handler errors: %errors', $args));
+    $this->assertTrue($valid_input == $valid_form, 'Input values: %values<br/>Validation handler errors: %errors', $args);
+++ b/core/modules/system/lib/Drupal/system/Tests/System/ErrorHandlerTest.phpundefined
@@ -93,15 +93,15 @@ class ErrorHandlerTest extends WebTestBase {
-    $this->assertText($error_pdo_exception['%type'], t('Found %type in error page.', $error_pdo_exception));
-    $this->assertText($error_pdo_exception['!message'], t('Found !message in error page.', $error_pdo_exception));
+    $this->assertText($error_pdo_exception['%type'], 'Found %type in error page.', $error_pdo_exception);
+    $this->assertText($error_pdo_exception['!message'], 'Found !message in error page.', $error_pdo_exception);
ZenDoodles’s picture

FileSize
1.21 MB
807.41 KB

This one fixes Tim's too...

The new script:

for file in `grep -rl "assert[A-Za-z]*(.* t('[^')]*'));" core/modules/`
do
  mv $file $file.tmp
  sed  "s#\(assert[A-Za-z]*(.*\) t(\('[^')]*'\)));#\1 \2\);#g" $file.tmp > $file
  rm $file.tmp
  echo Fixed $file
done
ZenDoodles’s picture

Status: Needs work » Needs review
sun’s picture

Status: Needs review » Needs work
FileSize
194 bytes

Yes and no. They should be left out entirely for this patch.

Adjusted the script to skip all t()s that should be format_string(). Lame algorithm, but at least no false-positives. ;)

xjm’s picture

Thanks @sun and @zendoodles!

+++ b/core/modules/update/lib/Drupal/update/Tests/UpdateCoreTest.phpundefined
@@ -164,7 +164,7 @@ class UpdateCoreTest extends UpdateTestBase {
-    $this->assertNoRaw('<li>' . t('There is a security update available for your version of Drupal.'));
+    $this->assertNoRaw('<li>' . 'There is a security update available for your version of Drupal.');

Reading up from the bottom. Got to here. This change is not correct. (The message parameter is being omitted, so this is the first argument. t() should not be stripped.

Let's give sun's script a shot, compare the diffstats, interdiff it up, and make sure we don't change these.

ZenDoodles’s picture

Status: Needs work » Needs review
FileSize
1.21 MB
4.96 KB

Okay... now we also make sure it's not the first parameter. I *think* this actually found another problem when there are two spaces before the t() instead of one though, so I may follow-up with yet another.

ZenDoodles’s picture

FileSize
1.21 MB
4.95 KB

Fix the cases where t() is preceded by two spaces. interdiff.txt is to #201

ZenDoodles’s picture

Issue summary: View changes

Update summary with current status and detailed information for maintainers.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Link tag name.

sun’s picture

It's not really the initiatives I'm concerned about. CMI would be unaffected, too.

It's the 900+ other patches I'm concerned about. This patch literally changes every test case throughout core, so pretty much most of these 900 will have to be re-rolled.

Unlike the major patch re-roll doom that the PSR-0 test conversions already caused (which was required to unblock the huge API change of removing the registry for D8), it's not clear to me which major feature or API change depends on this.

If there is no such dependency, then I'd highly prefer to postpone and defer this commit to after feature freeze. That's the designated time for clean-ups. Committing it before feature freeze can easily mean that some major changes and new features won't make it into D8.

This is only underlined by the fact that the entire patch is scripted, so it can be redone within seconds at any point in time.

EDIT: That is why I only attached the script, but not a patch. So let's make sure to attach/maintain the latest+greatest script here.

ZenDoodles’s picture

@sun When to commit is above my pay-grade. I think the rationale for getting it in sooner rather than later is that we have a couple of sprints coming up where folks could do a lot of the re-rolling. My two cents... I would appreciate getting it in just so we don't miss the window again, but the implications you are concerned about would have little impact on me, except to the degree that I'd be be helping with re-rolls of those too. Either way I doubt all 900 issues will be affected by this patch.

I do agree re: the latest and greatest script - see attached. I understand .tmp is ugly when it fails, but alas, --in-place fails on my Mac.

ZenDoodles’s picture

FileSize
240 bytes

Okay... ACTUALLY attached now.

xjm’s picture

Regardless of when we commit this, there will be hundreds of patches that are at risk for needing rerolls. (Edited: They don't necessarily need rerolls.)

The longer we wait, the more people are confused and frustrated by the conflicted messages and inconsistency within core. I am so sick of answering this question I could scream. Even zendoodles did not understand the current status, even after reading the documentation and seeing the reference to this issue. And zendoodles is one of a handful of people mentoring dozens of novices on patch creation.

Next week we have the opportunity to have 50-100 people working on rerolls over a seven-day period. IMO, take advantage of that.

xjm’s picture

Status: Needs review » Needs work
+++ b/core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.phpundefined
@@ -26,11 +26,11 @@ class SessionTest extends WebTestBase {
-    $this->assertFalse(drupal_save_session(), t('drupal_save_session() correctly returns FALSE (inside of testing framework) when initially called with no arguments.'), t('Session'));
-    $this->assertFalse(drupal_save_session(FALSE), t('drupal_save_session() correctly returns FALSE when called with FALSE.'), t('Session'));
-    $this->assertFalse(drupal_save_session(), t('drupal_save_session() correctly returns FALSE when saving has been disabled.'), t('Session'));
-    $this->assertTrue(drupal_save_session(TRUE), t('drupal_save_session() correctly returns TRUE when called with TRUE.'), t('Session'));
-    $this->assertTrue(drupal_save_session(), t('drupal_save_session() correctly returns TRUE when saving has been enabled.'), t('Session'));
+    $this->assertFalse(drupal_save_session(), t('drupal_save_session() correctly returns FALSE (inside of testing framework) when initially called with no arguments.'), 'Session');
+    $this->assertFalse(drupal_save_session(FALSE), t('drupal_save_session() correctly returns FALSE when called with FALSE.'), 'Session');
+    $this->assertFalse(drupal_save_session(), t('drupal_save_session() correctly returns FALSE when saving has been disabled.'), 'Session');
+    $this->assertTrue(drupal_save_session(TRUE), t('drupal_save_session() correctly returns TRUE when called with TRUE.'), 'Session');
+    $this->assertTrue(drupal_save_session(), t('drupal_save_session() correctly returns TRUE when saving has been enabled.'), 'Session');

It says how often we use the $group parameter that I got up a good 20% of the way before encountering this, but... here we are stripping the translation from the group parameter instead of the message parameter.

ZenDoodles’s picture

Hm... Issue here is that it really depends on which assertion method is used...
Adjusting the regex to account for this means we catch both of these:

// core/modules/system/lib/Drupal/system/Tests/Session/SessionTest.php: 
$this->assertResponse(200, t('Session test module is correctly enabled.'), 'Session');
// Follows the pattern
$this->assertSomething($assertion, $message, $group);

//core/modules/comment/lib/Drupal/comment/Tests/CommentTestBase.php:
$this->assertNoFieldByName('op', t('Save'), 'Save button not found.'); 
// is actually...
$this->assertSomething($assertion, $value, $message[, $group]);

I have a solution, but it's getting more and more complex!

xjm’s picture

So we discussed this last night in IRC and then I slept on it. I was thinking of doing this like I did the core/ move, but there's a better way; we're freaking programmers. Here's what we do.

  1. Run a query on d.o to get a list of all file attachments to published core 8.x RTBC and NR issues. Dump the nid, status, priority, title, comment posted date, and file attachment name to a single denormalized database table for us to use. webchick will do this for us given a query. I'm about to download the drupalorg_testing profile and take a stab at writing it, because it's 4:30a and I just woke up.
  2. Run a query against this table to get the latest patch or diff attachment filenames per node ID.
  3. Inspect this data to look for cases where the latest patch attachment doesn't look like an 8.x patch filename, and adjust; look at those nodes manually if needed. There won't be many if any.
  4. Run a shell script to wget these down and apply each file to 8.x HEAD, then reset. Eliminate those that do not currently apply. Starting point for the shell script from chx:
    for p in `ls patches/*` ; do git apply $p; if [-z $] echo $p; fi; git reset --hard ; done
    
  5. Commit this issue's patch locally and repeat for the remaining patches. We then have a list of exactly which patches are affected by this.
  6. Get those files' nids from the table. We now have a list of all issues affected by the change, which I can suck into http://core.drupalofficehours.org/ and set the new contributors on. :)
xjm’s picture

We could even automate a script to see which apply with a rebase. Edit: And heck, even to reroll those that do.

xjm’s picture

Here's the query. I think I have the IDs correct in the WHERE clauses but might want to double-check them.

Edited to include attachments to the original post.

SELECT
pi.nid,
n.title,
n.created,
priority.name priority,
s.name status,
pic.timestamp,
pic.comment_number,
f.filepath

FROM project_issues pi
INNER JOIN node n ON n.nid = pi.nid
INNER JOIN project_issue_priority priority ON pi.priority = priority.priority
INNER JOIN project_issue_state s ON pi.sid = s.sid
LEFT JOIN project_issue_comments pic ON pi.nid = pic.nid
LEFT JOIN upload u ON u.nid = pi.nid
LEFT JOIN comment_upload cu ON cu.nid = pi.nid AND pic.cid = cu.cid
INNER JOIN files f ON u.fid = f.fid OR cu.fid = f.fid

WHERE
pi.pid = 3060 -- core
AND pi.rid = 572834 -- 8.x-dev
AND n.status = 1 -- published
AND pi.sid = 14 OR pi.sid = 8 -- RTBC or NR
xjm’s picture

Working on the shell script. I'm using the patches from current RTBCs to test it. Incidentally, of 30 issues, it looks like only a minority are even potentially affected. Good odds, so far.

xjm’s picture

So of 30 RTBC patches, among those that include anything in test files and currently apply to 8.x HEAD, only two failed to apply on top of the mostly-correct patch in #206. Of these two, one was resolved by a simple rebase and the other was not.

Here's the script that outputs a patch name if it doesn't apply. (I put it and the patches outside the repo for git clean.) Edited: steps.

  1. wget all the patches to /my/absolute/path/patches and mkdir /my/absoulte/path/needs_reroll and /my/absolute/path/needs_reroll.
  2. Run:
    git checkout -b tmp 8.x &> /dev/null
    for p in `ls /my/absolute/path/patches/*`
    do
      o=`git apply $p 2>&1`
      if [ $? != 0 ]
        then
          echo $p does not apply after assertion cleanup
          mv $p /my/absoulte/path/does_not_apply
      fi
      git reset --hard &> /dev/null
      git clean -fd &> /dev/null
    done
    git branch -D tmp &> /dev/null
    

    This moves all patches that do not apply to HEAD to the does_not_apply directory. Those are patches that can be ignored or deleted.

  3. Then do:
    git checkout -b assert_t 8.x &> /dev/null
    git apply --index assert_t_patchname.patch
    git commit -am "Assertion message cleanup."
    for p in `ls /my/absolute/path/patches/*`
    do
      o=`git apply $p 2>&1`
      if [ $? != 0 ]
        then
          echo $p does not apply
          mv $p /my/absoulte/path/needs_reroll
      fi
      git reset --hard &> /dev/null
      git clean -fd &> /dev/null
    done
    git branch -D assert_t &> /dev/null
    

    needs_reroll/ now contains all the patches that need to be rerolled.

  4. Script to try rebasing.
webchick’s picture

FileSize
1.28 MB

Here's the result of that query.

xjm’s picture

Excellent, thanks! Now comes the fun part.

I'll post a finished script when I'm done with it so anyone can play along at home.

xjm’s picture

Working shell script to rebase stuff. It totally produces the same results I got manually when I use my sample patch set. :D

[lorentz:assert_t_rerolls | Sat 15:13:03] $ ../test_and_rebase_patches.sh
Switched to a new branch 'tmp'
Switched to branch '8.x'
Deleted branch tmp (was 6885941).
2 patches did not apply to HEAD. They will be skipped.
Switched to a new branch 'assert_t'
[assert_t 4acd7e5] Assertion message cleanup.
 338 files changed, 3162 insertions(+), 3162 deletions(-)
2 patches need rerolls after the cleanup.
Rebasing /Users/xjm/git/needs_reroll/drupal8.list-options.73.patch failed.
1 patches were rerolled with rebase.

Now to get the full dataset... this will be fun.

xjm’s picture

Okay something didn't go right with the query because this is the first node:
http://drupal.org/node/11950

:D

xjm’s picture

Let's get some more feedback from the query:

SELECT
pi.nid,
pi.pid pi_pid,
pic.pid pic_pid,
pi.rid pi_rid,
pic.rid pic_rid,
n.title,
n.created,
priority.name priority,
s.name status,
pic.timestamp,
pic.comment_number,
f.filepath

FROM project_issues pi
INNER JOIN node n ON n.nid = pi.nid
INNER JOIN project_issue_priority priority ON pi.priority = priority.priority
INNER JOIN project_issue_state s ON pi.sid = s.sid
LEFT JOIN project_issue_comments pic ON pi.nid = pic.nid
LEFT JOIN upload u ON u.nid = pi.nid
LEFT JOIN comment_upload cu ON cu.nid = pi.nid AND pic.cid = cu.cid
INNER JOIN files f ON u.fid = f.fid OR cu.fid = f.fid

WHERE
pi.pid = 3060 -- core
AND pi.rid = 572834 -- 8.x-dev
AND n.status = 1 -- published
AND pi.sid = 14 OR pi.sid = 8 -- RTBC or NR

LIMIT 10
xjm’s picture

So davereid noticed a logic error on the last line... here's the correct query.

SELECT
pi.nid,
pi.pid pi_pid,
pic.pid pic_pid,
pi.rid pi_rid,
pic.rid pic_rid,
n.title,
n.created,
priority.name priority,
s.name status,
pic.timestamp,
pic.comment_number,
f.filepath

FROM project_issues pi
INNER JOIN node n ON n.nid = pi.nid
INNER JOIN project_issue_priority priority ON pi.priority = priority.priority
INNER JOIN project_issue_state s ON pi.sid = s.sid
LEFT JOIN project_issue_comments pic ON pi.nid = pic.nid
LEFT JOIN upload u ON u.nid = pi.nid
LEFT JOIN comment_upload cu ON cu.nid = pi.nid AND pic.cid = cu.cid
INNER JOIN files f ON u.fid = f.fid OR cu.fid = f.fid

WHERE
pi.pid = 3060 -- core
AND pi.rid = 572834 -- 8.x-dev
AND n.status = 1 -- published
AND (pi.sid = 14 OR pi.sid = 8) -- RTBC or NR

LIMIT 10
webchick’s picture

FileSize
218.03 KB

Let's try that again. :)

xjm’s picture

So I imported that data into a MySQL table, then ran the following queries on it to eliminiate irrelevant comments. I realized after the fact I may have accidentally deleted the attachments for the original posts (again) so I'll handle those separately.

DELETE FROM dump WHERE pic_pid <> 572834; -- 8.x-dev. This should have had AND pic_pid IS NOT NULL.
DELETE FROM dump WHERE filepath NOT LIKE '%.patch' AND filepath NOT LIKE '%.diff'; -- Non-patch attachments.
DELETE FROM dump WHERE filepath LIKE '%do-not-test.patch' -- Probably D7 patches.

Then, I ran the following query to get the latest attachment names:

SELECT nid, MAX(comment_number) comment_number, filepath FROM dump GROUP BY nid

Exported this to CSV and the result was the attached file. Then I ran the following shell script:

files=`cat most_recent.txt`
for line in $files
do
  IFS=', ' read -a array <<< "$line"
  nid=${array[0]}
  comment_number=${array[1]}
  filepath=${array[2]}
  wget -O patches/$nid-$comment_number.patch http://drupal.org/$filepath
done

Which downloaded all patches. Zipped up in the attached tarball. :)

Time to melt my processor.

xjm’s picture

Um. Wow.

[lorentz:assert_t_rerolls | Sat 17:25:27] $ ../test_and_rebase_patches.sh
Switched to a new branch 'tmp'
Switched to branch '8.x'
Deleted branch tmp (was 6885941).
625 patches did not apply to HEAD. They will be skipped.
Switched to a new branch 'assert_t'
[assert_t 66ee1a7] Assertion message cleanup.
 338 files changed, 3162 insertions(+), 3162 deletions(-)
4 patches need rerolls after the cleanup.
Rebasing /Users/xjm/git/needs_reroll/1618172-15.patch failed.
Rebasing /Users/xjm/git/needs_reroll/1670450-12.patch failed.
2 patches were rerolled with rebase.

Well. Most of those 652 skipped patches appear to not have been adjusted for the core/ move. That makes sense.

The other 237, though... can it really be that only 4 of them are broken? Is that remotely possible? These are the 4 it found as broken:
Rebased cleanly:
#1111224: Introduce .gitattributes to end the CRLF/LF and binary diff horror, and detect/auto-fix whitespace errors
#1543858: Add a startup configuration for the built-in PHP server that supports clean URLs

Rebase failed:
#1618172: Remove entity_uri() in favor of EntityInterface::uri()
#1670450: drupal_get_js() stable sort / drupal_add_js automatic weight

I went back and checked the verbose output, too. The non-skipped patches were all applied successfully, except for those for the four that were flagged as needing rerolls. It even reported whitespace errors and such for a lot of them.

I also grepped for "assert" in all the non-skipped patches. While there were 549 lines containing "assert," almost none of them used t() on the message parameter.

I even opened the files and started skimming them. Went through a couple dozen before I was convinced this might be real, maybe. (I still have doubts.) Really a tragic majority don't even have tests. Among the rest, there's added tests, but very rarely changed tests. And added tests are often a new class or method, so assertions aren't there as context lines.

Would be great if someone could double-check this.

xjm’s picture

One thing to double-check would be whether it is actually going through all those files and not terminating early for some reason. Add a counter. Maybe after dinner.

xjm’s picture

I added counters and got the same results:

[lorentz:assert_t_rerolls | Sat 19:47:43] $ ../test_and_rebase_patches.sh
Switched to a new branch 'tmp'
Switched to branch '8.x'
Deleted branch tmp (was 6885941).
627 patches did not apply to HEAD. They will be skipped.
627 were not applied.
262 were applied.
Switched to a new branch 'assert_t'
[assert_t 0b3f1c3] Assertion message cleanup.
 338 files changed, 3162 insertions(+), 3162 deletions(-)
2 patches need rerolls after the cleanup.
2 failed to apply.
260 were applied.
Rebasing /Users/xjm/git/needs_reroll/1618172-15.patch failed.
Rebasing /Users/xjm/git/needs_reroll/1670450-12.patch failed.
2 patches were rerolled with rebase.
Already on '8.x'
Deleted branch assert_t (was 0b3f1c3).

So, if there is a bug, I don't think it's in the script.

xjm’s picture

Hmm, the two it says failed to rebase make sense (there are assertions in the context), but the two it says rebased are nonsense, and it turns out the files are empty for me locally. Probably just a download fail.

David_Rothstein’s picture

For Drupal 7 I don't think we should commit a patch like this at least until all the 7.15 release blockers are resolved...

Whether it makes sense to do this for Drupal 7 and 8 around the same time, I'm not sure.

Earlier in this issue, @webchick also had concerns about ever backporting this to Drupal 7. I'm not sure if those concerns were resolved? (But the issue still has the "needs backport to D7" tag.) Since the codebase is so inconsistent right now (with different code following different standards depending on when it was added or changed) and that inconsistency exists in both Drupal 7 and Drupal 8, I suppose we need to do something to fix it, whatever that something turns out to be.

I'd hate to say it, though, but after reading this issue I'm adding myself to the list of people who don't understand what the motivation for moving away from t() actually is.... The only real problem it fixes seems to be the pollution of {locales_source}, but @sun pointed out a long time ago that we could fix the internals of t() itself to avoid doing that while tests are running (and we probably should anyway, since it's not like we'll ever get all contrib modules to stop using t() on assertion messages). And performance seems like a red herring; there's no reason to micro-optimize the test suite like that.

That said, I don't think it's a big deal either way, and at least for Drupal 8, whatever we do to make things consistent at this point is better than things not being consistent :)

boombatower’s picture

I mean I understand the reasons behind deferring, but lordy this has been deferred since July 2009. It might be time to get on with it.

xjm’s picture

Untagging.

Crell’s picture

Wasn't this supposed to happen a month ago? We're running into test failures caused by t() in assertions (#1215104: Use the non-interactive installer in WebTestBase::setUp()), so sooner rather than later would be good here.

lazysoundsystem’s picture

For reasons outlined above, this might not be the best method - I managed to miss this issue before starting work on this - but..

I made a start on changing these module by module, so it's not so frightening to review. I also used grep and a couple of macros, so each has been checked along the way.

If it's worth keeping on with this approach, I'll be happy to continue.

I created a separate issue for each module:
Aggregator: #1741328: Remove t() from asserts messages in tests for aggregator module
Block: #1741338: Removing t() from asserts in simpletests in block module
Book: #1741386: Removing t() from asserts in simpletests in book module
Comment: #1742602: Removing t() from asserts in simpletests in comment module
Contact: #1742830: Removing t() from asserts in simpletests in contact module

boombatower’s picture

I don't see how making more work on an issue that has already required way more than needed is a good thing (dragging out caused loads of rerolls and now dozen+ methods/scripts/manual rolls and manually reading the rerolls). Now we are just going to drag out the rerolling of core patches affected by this for weeks/months as these go in...just get on with it. This issue is a prime examples of why people get burned out and/or don't bother working on core.

Lars Toomre’s picture

I reviewed the four open issues in #234 and reviewed the appropriate patches. All changes removing t() around assertion messages were correct. So I RBTC the patches for aggregator, block and contact modules. The comment module patch no longer applies and will need to be re-rolled.

My guess is that those three patches alone will reduce 50+ calls to t() around assertion messages. Hurray!!

Lars Toomre’s picture

I am working on removing t() from assert messages in tests for the system module. There are so many assertions there that it has to be broken up into smaller pieces. For instance, just converting the tests associated with includes A-C has about 500 line changes (primarily in bootstrap and common tests).

What is a reasonable number of changes to include in one patch file? Approximately 50, 100, 250 or 500? Thoughts are welcome and then I will create appropriate issues with the right size patches. Time to start working down all of the unnecessary t() assertion messages in core!!

Lars Toomre’s picture

Opened issue #1794012: Remove t() from asserts for database system tests to remove the approximately 350 t() assertions in the tests for the database system. A patch will be forthcoming there shortly.

podarok’s picture

Status: Needs work » Needs review
Issue tags: -Needs backport to D7, -best practices change

#206: assert_t-500866-206.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +Needs backport to D7, +best practices change

The last submitted patch, assert_t-500866-206.patch, failed testing.

jhodgdon’s picture

The sub-issues related to this patch should be put into the issue summary so we can track progress.

xjm’s picture

Taxonomy was cleaned up already in #1195254: Taxonomy test cleanup.

By module does seem the way to go, since I couldn't get through @ZenDoodles' full patch in 3 hours.

I'll update the summary.

xjm’s picture

Title: Simpletest: remove t() from assert message » [META] remove t() from assert message

And calling this a meta.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

In follow-up to #237, I created #1797120: Remove t() from asserts for A-C includes system tests and posted an initial patch which cleans up approximately another 400 uses of t() around assert messages. Reviews would be welcome because it covers tests in Bootstrap and Common include files among others. I will add it to the summary as well in a moment.

Lars Toomre’s picture

Issue summary: View changes

.

xjm’s picture

Tip for reviewing these: Apply the patch locally and do git diff --color-words.

xjm’s picture

Also, another suggestion: To make reviewing these more sane, if it's okay with @ jhodgdon, let's split up the simple messages from the ones that need format_string() replaced if the patch is really large? If they're smaller I'm indifferent, but even the 65k-ish comment one took me a long time to review, and it looks like @Lars Toomre's patch for system A-C tests is close to 200K.

xjm’s picture

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

I forgot we already had #1681890: Use format_string() instead of t() for assertion message text. I'll try to make note above of which modules have already had format_string() subbed in where appropriate.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary. Added reference to issue #1797220: Remove t() from asserts from Entity sub-system tests.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

I updated the summary and have now posted at patch for #1797220: Remove t() from asserts from Entity sub-system tests. This one is "only" ~50kb in size. However, to facilitate both commiting it in D8 and then back porting to D7, I purposely have limited it to only 120 changes. If I recall correctly, it also has no format_string() changes.

This patch will be more difficult to review as noted in the summary for #1797220: Remove t() from asserts from Entity sub-system tests. @xjm's suggestion in #245 is very much applicable here.

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

jhodgdon’s picture

RE #246 - I am OK with either way (combined or separate patches).

RE #247 - I would be in favor of closing that second issue as a duplicate of this one, whether patches combine the simple "remove t() from strings" and the slightly more complicated "use format_string() for substitutions instead of t()", or we have two separate patches. I'm also fine with splitting up individual issues into several separate patches so they are not so large -- doing one, waiting for commit, then doing another. Whatever works. :)

jhodgdon’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

Issue summary: View changes

Added link to issue #1797296: Remove t() from asserts from File system tests for File sub-system

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Alright, I closed #1681890: Use format_string() instead of t() for assertion message text as a duplicate. I've also added several more issues to the summary.

xjm’s picture

Issue summary: View changes

Cleaning up sub-system formatting

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

xjm’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

I have added issues that complete the coverage of all sub-systems of the system module. It looks like these subsystems accounted for more than 1,500 of the t() assertions covered by this issue. Hence, it would be really helpful to get these particular issues reviewed and committed. Thanks for your help @xjm!

I also opened #1797940: Fix docs for helper method in language tests as a catch all for follow-ups from this initiative for things like incomplete docblocks or incorrect use of t() in getInfo() functions.

cosmicdreams’s picture

I love this description. This is a very good place for any level of Drupal dev to help out.

cosmicdreams’s picture

Issue summary: View changes

Updated for remaining sub-system issues.

Lars Toomre’s picture

Issue summary: View changes

Added issue for the tracker module.

Lars Toomre’s picture

Issue summary: View changes

Added issue for Translation module.

Lars Toomre’s picture

Issue summary: View changes

Added issue for Update module.

Lars Toomre’s picture

Issue summary: View changes

Added issue for User module.

Lars Toomre’s picture

I believe there are now at least D8 initial patches in all of the sub-issues listed in the summary of this issue. It would be great to get some reviews completed so that we can complete this long outstanding issue. Thanks for your help.

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary.

boombatower’s picture

It seems a tad inaccurate that all the people who helped out in this issue over the several years are not attributed on the commits from all the other issues.

55aebf4 Issue #1797376 by xjm: Remove t() from test assertions in poll module
22f7076 Issue #1797374 by xjm: Remove t() from test assertions in PHP module
74d0529 Issue #1797170 by xjm: Remove t() from test assertions in field_ui.module
1451a54 Issue #1797296 by Lars Toomre: Remove t() in test assertions in file sub-system
45b4961 Issue #1742602 by xjm, lazysoundsystem: Remove t() from test assertions in comment module
b5acb7b Issue #1797242 by xjm: Remove t from dblog test assert messages
fe147ab Merge branch '8.x' of git.drupal.org:project/drupal into 8.x
e91b1b5 Issue #1797228 by xjm: remove t from test assertions in config module
6824ba0 Issue #1696640 by fago, effulgentsia, tim.plunkett, dixon_, plach: Add a uniform Entity Property API.
b9af7fe Issue #1797120 by Lars Toomre: Remove t from test assertion messages in system tests A-C
5c39787 Issue #1797370 by xjm: Remove t() from assertion messages in tests for the openid module.
88209f1 Issue #1797106 by xjm: Remove t() from asserts messages in tests for the field module.
fd5ab15 Issue #1797330 by xjm: Remove t() from assertion messages in tests for the help module.
0bca40b Issue #1797328 by xjm: remove t() from assertion messages in tests for the image module.
boombatower’s picture

Issue summary: View changes

Added sub-issue reference for the ban module.

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

@jhodgdon - From my perspective the most important of the sub-issues to address is making a first commit for the node module. We then need to roll an additional patch to clean up format_string() conversions plus whatever else remains. I believe all of the other sub-issues are pretty much complete (except for a stray t() that may have been missed).

andypost’s picture

jhodgdon’s picture

RE #254 - when I make a commit, I usually try to look through the issue and attribute people who have supplied patches. If others have contributed, please make comments on the issues so I know who to attribute.

jhodgdon’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

Issue summary: View changes

Updated issue summary.

Lars Toomre’s picture

Added the related issues from #256 to the issue summary.

boombatower’s picture

Pressing the create commit message button on this issue results in:

Issue #500866 by pillarsdotnet, boombatower, solotandem, ZenDoodles, sun, xjm, yched, Damien Tournoud | neochief: [META] remove t() from assert message.

Which provides a rough idea of the large number of people who have put in significant effort into this issue.

jhodgdon’s picture

I am not trying to belittle the work that was done previously here, but if a lot of people do work on an issue and then the patch is never accepted, we don't credit them with having worked on a failed patch generally, as far as I know.

I was under the impression that the work being done on each of the sub-issues of this now-meta-issue is pretty much independent of whatever was done previously on this issue. If that's not the case, let me know and I can certainly credit people who actually helped in making patches that are being committed.

boombatower’s picture

Since we had the conversation in IRC might as well summarize my point.

I agree when an direction on an issue is abandoned we don't usually credit them (although failed directions can be useful). This patch was 100% functional, was accepted as the way to do it, but was delayed (which is something in hindsight that has caused far more damage then the perceived disruption of large changes).

The smaller issues are probably start from scratch, which in this case is quite irrelevant since the direction of the patch is identical. The scripts made available by multiple individuals to do the process automatically could be used and it is simply poor choice not to.

Overall, this is just another example that we should try to take into account not to arbitrarily kill issues.

jhodgdon’s picture

Yeah... agreed on everything you are saying.

So how about this. There are 2 more patches for this now-meta-issue that haven't been committed (I think there are only two). If you add a comment to one of them detailing who else should get a commit credit for the patches, I'd be happy to add them. The two I know about that haven't gone in yet are:
#1797200: Remove t() from assertion messages in node.module tests
#1797220: Remove t() from asserts from Entity sub-system tests

Of course, as pointed out by chx in IRC, the whole "system" we have for counting contributions to Drupal core via number of commit message mentions is stupid anyway -- it doesn't come close to measuring the importance of the patch, the level of effort required to do the patch, or even the number of bytes of changed code. Not to mention that reviewing and discussing (and maybe committing? :) ) are not counted by this measure at all. So probably we ought to focus (at least partially) on number of bytes of comments on issues rather than number of commit credits... or ... well a lot of that stuff is hard to measure. I personally appreciate everyone who takes the time to review a patch that I commit, or wrote up a good issue report in the first place, and always feel a stab of sorrow when in my commit message I am only supposed to credit those who created an actual patch file. The credit system is flawed...

Anyway. Do go and add a comment to those issues making a case for crediting people from this issue and I'll at least make sure they get a mention if I commit them. That's about all I can do at this point to remediate.

xjm’s picture

Just like to put out here that I spent more time on this one stupid issue over the summer than any 10 other patches I've worked on, and that the recent decision to break it into per-module patches and keeping the scope narrow unblocked it when it's been stuck for years. And that reviewing these patches takes exponentially more time than creating them.

boombatower’s picture

I think that you will find that same sentiment from all those involved in this issue...I know I do (and solotandem). Rolling a patch without really looking it over and the code doesn't take _too_ long, but confirming it is correct as I and many others did repeatedly takes quite a significant amount of time.

Issues like this can easily have followups and the amount of human time wasted by all parties is absurd and should be taken into consideration before delaying such patches in the future...just commit it.

I am happy to see this finally get in and appreciate everyone's efforts towards this issue. I hope we can learn from this and not repeat it.

xjm’s picture

and always feel a stab of sorrow when in my commit message I am only supposed to credit those who created an actual patch file. The credit system is flawed.

I disagree with this; IMO contributing significant review can merit commit mention. I know webchick adds reviewers to commit messages, particularly on important issues. I guess it's just not something that dreditor can auto-generate, and so it adds additional burden on committers.

Lars Toomre’s picture

Thanks @xjm for all of your efforts on this issue. Through your efforts either as creator of the patch or reviewer, it looks like about half of the sub-issues have now been committed to D8.

There are about 25 D8 sub-issue patches ready for review. Hopefully, we can get other reviewers involved so all can be committed to D8, backported to D7, and we finally can close out this issue after being open for several years.

jhodgdon’s picture

The vast majority of patches I've committed to core, I've been the reviewer. :) Anyway, the credits for patches/reviews are not being done consistently by all committers, and not always accurately anyway, and besides which the idea that the number of commit credits is any kind of a good measure of "contribution to core", much less "contribution to Drupal" is flawed.

That said... In the last two days, I did add all of the people that boombatower mentioned (hopefully I got everyone) to one of the commit messages on this issue, so everyone did at least get one commit credit.

jhodgdon’s picture

Ugh. I just noticed that at least in D7, the base test classes are using t() to generate the default assertions, such as this one in assertNotNull():

return $this->assert(isset($value), $message ? $message : t('Value @value is not NULL.', array('@value' => var_export($value, TRUE))), $group);
}

Are these on the docket to be fixed too? Hopefully? :)

jhodgdon’s picture

It looks like a separate issue for the base test classes is probably a good idea, so I filed:
#1803674: Remove t() from default test assertions in TestBase class
and I'll add it to the summary.

jhodgdon’s picture

Issue summary: View changes

Updated issue summary.

jhodgdon’s picture

Anyone want to go review a patch for a related issue in the Examples for Developers project:
#1803844: Remove t() from test assertion messages
that would be helpful... :)

jhodgdon’s picture

Related issue
#1813286: _simpletest_format_summary_line() should not use t()
(not sure if it should be a sub-issue of this or not)

jhodgdon’s picture

Issue summary: View changes

added base classes sub-issue

jhodgdon’s picture

Issue summary: View changes

add one to the list

klausi’s picture

Cross posting from #1838596-57: Add deserialize for JSON-LD:

It is totally wrong to use format_string() in assertion messages. format_string() should be used when user provided input is involved as its purpose is to sanitize variables. Since 99.99% of all assertion messages don't need sanitization this is just a waste of function calls and CPU cycles. Standard string concatenation or inline replacements like "Verified that $format has been saved" are fine.

What am I missing?

sun’s picture

That's my stance, too, and is also in line with non-Drupal tests. That said, it's not about user input (since there is no unknown user input in tests) but about escaping and sanitizing strings for HTML output.

However, there was some pushback that certain variables need to be escaped before they are printed (e.g., randomString() produces garbage, which potentially contains characters that need to be escaped for HTML to prevent them from e.g. breaking the test results page), and thus, these exceptions would have to be explained to developers and test authors.

That counter-argument is seemingly correct, because most Drupal developers today know close to nothing about string handling anymore, as we've essentially invested years of manpower to teach them: "When in doubt, simply and always use t() with @ or % placeholders."

I think it is the identical reason for why we frequently have random test failures caused by randomString() vs. randomName(), since a assertText() or assertRaw() will suddenly fail if the random string happens to contain characters that need to be escaped in HTML. These random test failures scared developers so much that they started to shy away from using randomString() in tests (up to the point of suggesting to remove the function), even though assertions for the escaping and sanitization of strings should be part of every (dedicated) UI test, in order to verify that it is secure.

Just had an idea to improve at least that last situation: #1860594: Ensure that randomString() always returns a character that needs to be escaped for HTML

However, that doesn't change anything with regard to format_string() in tests and awareness/knowledge of when it is needed.

jhodgdon’s picture

It was also much easier for the people creating/reviewing the patches that removed the use of t() [which was important so that all the test assert messages wouldn't come up on localize.drupal.org any more] to just have a rule to follow "Use format_string()" rather than having to think hard about "Well if this might be unprintable, we'd better use format_string, but if not we can just concatenate strings".

David_Rothstein’s picture

It sounds like the main issue here [edit: by "here" I mean what was raised a couple weeks ago in comments #272-#274] is that the documentation of format_string() needs to be improved? Currently it emphasizes the security aspect, which is a big part of it but not the whole purpose. Its overall purpose is to prepare unknown strings for display as HTML.

It's true that if you know exactly what characters your $variable might contain and none of them will be interpreted as unwanted HTML, you technically don't need format_string(). But it's a whole lot easier to use it and just go with the @variable placeholder anyway; it makes the code easier to read, easier to change later, and a better example for people who might be copying it as a model for use in other situations.

I created #1873608: Improve documentation of format_string() to emphasize that it is used to prepare variables for HTML display to deal with the documentation issue.

sun’s picture

Meanwhile I think that neither t() nor format_string() are up to the task, nor the right tool for the job. Both of them focus on user-facing UI messages.

Messages printed in tests, however, are dealing with a special type of replacement tokens: Raw data.

The sole and only purpose of custom assertion messages is to provide more meaningful output to PHP developers when running tests. As such, format_string() is helpful to get the basic task of sanitization done, but it fails to properly delimit and dump the data.

For example: "@first is equal to @second." may print:

The world is equal to .

Achieved: Sanitized output.

Not achieved: Useful output.

Point being, test authors and developers are interested in raw PHP data, not fancy user messages. If "The world" was a string and not part of the assertion message, then I need to know that not the world is nothing, but the string 'The world' is nothing. And needless to say, I need to know to what kind of nothing 'The world' is actually equal to - an empty string? NULL? FALSE, mayhaps?

What we actually need in tests is a ::formatString() that leverages var_export() to produce assertion messages that are meaningful for test authors and developers — not users.

I've started to implement this in #1601146: Allow custom assertion messages using predefined placeholders

Anonymous’s picture

Wouldn't it be great (and the correct workflow as outlined in the "Review patches" documentation) to just finish this meta task and its sub tasks and afterwards introduce an improved solution? We are currently at comment #276+ and the issue is 33 month old.

It might also be possible to commit the patches to d8 and skip the d7 back porting?

Best regards, Dirk

xjm’s picture

@schoobidoo No one has to pay rent to keep an issue open until it is resolved. :)

jhodgdon’s picture

Assigned: ZenDoodles » Unassigned

There are only **9** open issues left on this huge effort!

Quite a few of them are at "needs review", and one or two have patches that need a little work. I'm going to go hit retest on the existing patches... maybe we can finish this up during June? :)

star-szr’s picture

Status: Needs work » Active
FileSize
40.19 KB
29.68 KB

We do have some stragglers at this point even though only #1797364: Remove t() from assertion messages in tests for the locale module is pending.

We are very close but there is a bit more work to do to fully remove t() from assert messages in core. Warning: the regular expression does return some false positives. The lists below are almost definitely not perfect :)

Drupal 8

grep -rl "assert[A-Za-z]*(.* t('[^')]*'));" core/modules/

I propose that other than Views and Views UI we handle all the remaining Drupal 8 t() assertion messages via a "stragglers" issue (maybe a helper issue so we don't go over 300 comments on this one!) since they are quite scattered but not a huge number of them - somewhere around 40 assertion messages if we exclude the pending locale patch, Views, and Views UI. Very manageable I think.

So we can create issues for:

  • views
  • views_ui

And the straggler/helper issue can handle these (list may not be 100% correct but is a starting point):

  • content_translation
  • entity_reference
  • field_sql_storage
  • toolbar
  • field_ui
  • node
  • system tests:
    • core/modules/system/lib/Drupal/system/Tests/Database/UpdateTest.php
    • core/modules/system/lib/Drupal/system/Tests/Image/ToolkitTest.php
    • core/modules/system/lib/Drupal/system/Tests/Module/ModuleApiTest.php - not sure about this one
    • core/modules/system/lib/Drupal/system/Tests/System/AdminMetaTagTest.php and
      core/modules/system/lib/Drupal/system/Tests/System/DefaultMobileMetaTagsTest.php
  • core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTestPhpTemplate.php and
    core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php
  • taxonomy
  • user

Drupal 7

grep -rl "assert[A-Za-z]*(.* t('[^')]*'));" modules/

More assertions remaining than Drupal 8, individual issues should be created to patch Drupal 7 only modules:

  • blog
  • dashboard
  • profile
  • trigger

The following issues may need to be re-opened to fix some stragglers (mostly simpletest and system), I'm not 100% sure about menu or node though, those only have 1 each and should probably be checked by someone more familiar with how these patches go in Drupal 7. Maybe there is some discussion on the issues:

Attaching the (untouched) results of a current grep -r for Drupal 7 and 8 as well, and setting to 'active' because this is a meta issue.

lazysoundsystem’s picture

Good idea and good report. The false positives are generally assert messages that use different numbers of parameters, or don't take messages (like assertBreadcrumb), but there are a couple to watch out for which are concatenations rather than arguments.

Created a new issue for the stragglers - #2035077: removing t() from asserts - remaining changes.. First patch for 8.x ready to review.

lazysoundsystem’s picture

Issue summary: View changes

Updated issue summary.

lazysoundsystem’s picture

And for the views and views_ui at #2035087: removing t() from asserts - remaining views and views_ui changes. And added both to the summary.

jhodgdon’s picture

Yeah let's open new issues rather than reopening old ones at this point. Thanks for the new issues -- I'll see about getting them committed shortly since it looks like they are already RTBC.

jhodgdon’s picture

Status: Active » Fixed

THIS ISSUE IS FINALLY DONE!!!!!!!!!!!

The only open issue in the list in the issue summary is not really in scope:
#1601146: Allow custom assertion messages using predefined placeholders
I still think it would be nice to fix that one, and if someone wants to take it over and do a patch, that would be really great. But I think we can now close this meta-issue.

And cheers were heard from far and wide...

Thanks to everyone who participated!!!!!!!

dcam’s picture

Woohoo!

dcam’s picture

Issue summary: View changes

Updated issue summary. added reference to two more related tickets.

star-szr’s picture

webchick’s picture

Note: Might want to tag those "coding standards" so they get on Jennifer's radar.

star-szr’s picture

Good idea, done! Thanks @webchick.

jhodgdon’s picture

That wasn't necessary. They were already on my radar.

jhodgdon’s picture

Issue summary: View changes

Add Drupal 7 issues

nlisgo’s picture

Issue tags: -

I'm sorry to report that there appears to be a bunch of new instances of t() in the assertion method in 8.0.x. The following search grep

-rl "assert[A-Za-z]*(.* t('[^')]*'));" core/modules/

returns these results on 8.0.x

core/modules/comment/src/Tests/CommentValidationTest.php
core/modules/config/src/Tests/ConfigExportUITest.php
core/modules/config/src/Tests/ConfigImportUITest.php
core/modules/field/src/Tests/Migrate/d6/MigrateFieldTest.php
core/modules/file/src/Tests/DownloadTest.php
core/modules/file/src/Tests/Views/FileViewsFieldAccessTest.php
core/modules/language/src/Tests/LanguageSwitchingTest.php
core/modules/search/src/Tests/SearchNodeUpdateAndDeletionTest.php
core/modules/system/src/Tests/Database/UpdateComplexTest.php
core/modules/system/src/Tests/Entity/EntityTypeConstraintsTest.php
core/modules/system/src/Tests/Entity/EntityValidationTest.php
core/modules/system/src/Tests/Extension/ModuleHandlerTest.php
core/modules/system/src/Tests/File/StreamWrapperTest.php
core/modules/system/src/Tests/Form/ElementsLabelsTest.php
core/modules/system/src/Tests/Form/ElementsVerticalTabsTest.php
core/modules/system/src/Tests/Menu/BreadcrumbTest.php
core/modules/taxonomy/src/Tests/TermLanguageTest.php
core/modules/taxonomy/src/Tests/TermValidationTest.php
core/modules/taxonomy/src/Tests/Views/TaxonomyRelationshipTest.php
core/modules/update/src/Tests/UpdateContribTest.php
core/modules/update/src/Tests/UpdateCoreTest.php
core/modules/user/src/Tests/UserValidationTest.php
core/modules/user/src/Tests/Views/AccessPermissionTest.php
core/modules/views/src/Tests/Plugin/DisplayPageWebTest.php
core/modules/views_ui/src/Tests/CachedDataUITest.php
core/modules/views_ui/src/Tests/DisplayAttachmentTest.php

I suggest we create a new single issue to clean these up.

nlisgo’s picture

Issue summary: View changes
jhodgdon’s picture

Uses of t() in asserts are not necessarily violations of this policy. For instance, looking at CommentValidationTest (the first class on the list in #290), I see this:

    $this->assertEqual($violations[0]->getMessage(), t('The name you used (%name) belongs to a registered user.', array('%name' => 'test')));

This is NOT an assert message. This is the 2nd argument to assertEqual, so it is asserting that the violation message is equal to t('The name you used.... This is correct.

All of the other uses of t() in this class are also fine. So I think we can leave this issue closed for 8.x. If you check the others carefully and find any t() in actual assert messages, please open up new 8.x issues rather than posting here.

nlisgo’s picture

@jhodgdon I accept the weakness of the grep criteria now. It is not going to be as easy I as I hoped to identify incorrect uses of the t() function for the assert methods but it doesn't change the fact that there are a few present in the codebase still. I also accept that this should be a new issue and have opened one here: #2552067: Remove t() from assertion messages in tests.

  • webchick committed 735e1d9 on 8.3.x
    #500866 by boombatower: Remove t() from getInfo in tests.
    
    
  • webchick committed 25171a1 on 8.3.x
    Reverting #500866. Needs more discussion.
    
    
  • webchick committed cacd044 on 8.3.x
    #500866 by boombatower, solotandem: Remove t() from assertion messages...

  • webchick committed 735e1d9 on 8.3.x
    #500866 by boombatower: Remove t() from getInfo in tests.
    
    
  • webchick committed 25171a1 on 8.3.x
    Reverting #500866. Needs more discussion.
    
    
  • webchick committed cacd044 on 8.3.x
    #500866 by boombatower, solotandem: Remove t() from assertion messages...

  • webchick committed 735e1d9 on 8.4.x
    #500866 by boombatower: Remove t() from getInfo in tests.
    
    
  • webchick committed 25171a1 on 8.4.x
    Reverting #500866. Needs more discussion.
    
    
  • webchick committed cacd044 on 8.4.x
    #500866 by boombatower, solotandem: Remove t() from assertion messages...

  • webchick committed 735e1d9 on 8.4.x
    #500866 by boombatower: Remove t() from getInfo in tests.
    
    
  • webchick committed 25171a1 on 8.4.x
    Reverting #500866. Needs more discussion.
    
    
  • webchick committed cacd044 on 8.4.x
    #500866 by boombatower, solotandem: Remove t() from assertion messages...
amit0212’s picture

Use -Wno-unused-value to stop the warning; (the option -Wall includes -Wunused-value).

I think even better is to use another method, like

assert(condition && "message");

xjm’s picture

Version: 7.x-dev » 8.0.x-dev
Status: Active » Fixed

At this point, I don't think this change is worth backporting to D7. Nothing is backportable from 8.x to 7.x anyway, especially since the entire testing API is different.

So, I'm marking this back to fixed against 8.0.x-dev, so that the issue does not continue to get bumped every time we create a new branch of Drupal.

Thanks everyone!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.