Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.375
diff -u -p -r1.375 form.inc
--- includes/form.inc	21 Sep 2009 06:44:13 -0000	1.375
+++ includes/form.inc	26 Sep 2009 00:00:57 -0000
@@ -2635,7 +2635,7 @@ function theme_form_element($element) {
   }
 
   $output = '<div class="' . implode(' ', $class) . '">' . "\n";
-  $required = !empty($element['#required']) ? '<span class="form-required" title="' . $t('This field is required.') . '">*</span>' : '';
+  $required = !empty($element['#required']) ? theme('form_required_marker', $element) : '';
 
   if (!empty($element['#title']) && empty($element['#form_element_skip_title'])) {
     $title = $element['#title'];
@@ -2659,6 +2659,26 @@ function theme_form_element($element) {
 }
 
 /**
+ * Theme the marker for required form elements.
+ *
+ * @param $element
+ *   An associative array containing the properties of the element.
+ * @return
+ *   A string representing the marker to identify required form elements.
+ *
+ * @ingroup themeable
+ */
+function theme_form_required_marker($element) {
+  // This is also used in the installer, pre-database setup.
+  $t = get_t();
+  $attributes = array(
+    'class' => 'form-required',
+    'title' => $t('This field is required.'),
+  );
+  return '<span' . drupal_attributes($attributes) . '>*</span>';
+}
+
+/**
  * Sets a form element's class attribute.
  *
  * Adds 'required' and 'error' classes as needed.
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.995
diff -u -p -r1.995 common.inc
--- includes/common.inc	25 Sep 2009 15:20:12 -0000	1.995
+++ includes/common.inc	26 Sep 2009 00:01:00 -0000
@@ -4724,6 +4724,9 @@ function drupal_common_theme() {
     'form_element' => array(
       'arguments' => array('element' => NULL),
     ),
+    'form_required_marker' => array(
+      'arguments' => array(),
+    ),
     'text_format_wrapper' => array(
       'arguments' => array('element' => NULL),
     ),
Index: modules/simpletest/tests/form.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/form.test,v
retrieving revision 1.16
diff -u -p -r1.16 form.test
--- modules/simpletest/tests/form.test	25 Sep 2009 17:18:41 -0000	1.16
+++ modules/simpletest/tests/form.test	26 Sep 2009 00:01:01 -0000
@@ -51,6 +51,9 @@ class FormsTestCase extends DrupalWebTes
     $elements['file']['element'] = array('#title' => $this->randomName(), '#type' => 'file');
     $elements['file']['empty_values'] = $empty_strings;
 
+    // Regular expression to find the expected marker on required elements.
+    $required_marker_preg = '@<label.*<span class="form-required" title="This field is required\.">\*</span></label>@';
+
     // Go through all the elements and all the empty values for them
     foreach ($elements as $type => $data) {
       foreach ($data['empty_values'] as $key => $empty) {
@@ -69,19 +72,33 @@ class FormsTestCase extends DrupalWebTes
           drupal_prepare_form($form_id, $form, $form_state);
           drupal_process_form($form_id, $form, $form_state);
           $errors = form_get_errors();
+          // Form elements of type 'radios' throw all sorts of PHP notices
+          // when you try to render them like this, so we ignore those for
+          // testing the required marker.
+          $form_output = ($type == 'radios') ? '' : drupal_render($form);
           if ($required) {
             // Make sure we have a form error for this element.
             $this->assertTrue(isset($errors[$element]), "Check empty($key) '$type' field '$element'");
-          }
-          elseif ($type == 'select') {
-            // Select elements are going to have validation errors with empty
-            // input, since those are illegal choices. Just make sure the
-            // error is not "field is required".
-            $this->assertTrue((empty($errors[$element]) || strpos('field is required', $errors[$element]) === FALSE), "Optional '$type' field '$element' is not treated as a required element");
+            if (!empty($form_output)) {
+              // Make sure the form element is marked as required.
+              $this->assertTrue(preg_match($required_marker_preg, $form_output), "Required '$type' field is marked as required");
+            }
           }
           else {
-            // Make sure there is *no* form error for this element.
-            $this->assertTrue(empty($errors[$element]), "Optional '$type' field '$element' has no errors with empty input");
+            if (!empty($form_output)) {
+              // Make sure the form element is *not* marked as required.
+              $this->assertFalse(preg_match($required_marker_preg, $form_output), "Optional '$type' field is not marked as required");
+            }
+            if ($type == 'select') {
+              // Select elements are going to have validation errors with empty
+              // input, since those are illegal choices. Just make sure the
+              // error is not "field is required".
+              $this->assertTrue((empty($errors[$element]) || strpos('field is required', $errors[$element]) === FALSE), "Optional '$type' field '$element' is not treated as a required element");
+            }
+            else {
+              // Make sure there is *no* form error for this element.
+              $this->assertTrue(empty($errors[$element]), "Optional '$type' field '$element' has no errors with empty input");
+            }
           }
         }
       }
