2 wordpress loops showing 1 post from same post type – how to avoid showing the same post?

Your two queries are identical, meaning you only need one of them. The basic solution is:

global $testimonials;
$testimonials = new WP_Query(array(
    'posts_per_page' => 2, /* <-- get both */
    'post_type'     => 'testimonial',
    'post_status'   => 'published',
    'orderby'   => 'rand',
    'ignore_sticky_posts' => true /* you need this to control post count accurately */     
));

// header
if ($testimonials->have_posts()) {
  while($testimonials->have_posts()) {
    $testimonials->the_post();
    // whatever you need to do with the post content
    break; // stop the Loop; no complex logic needed since you are printing one and moving on
  }
}

// sidebar
// pretty much the same as the above
global $testimonials;
// this Loop will pick  up where the other left off
if (!empty($testimonials) && $testimonials->have_posts()) {
  while($testimonials->have_posts()) {
    $testimonials->the_post();
    // whatever you need to do with the post content
  }
}

There are probably better ways to do this. I’d strongly consider rolling the whole thing into a class and avoiding the global altogether.

class Testimonial_Loop {
  static $testimonials = false;

  function get_testimonials() {
    if (empty(static::$testimonials)) {
      static::$testimonials = new WP_Query(array(
        'posts_per_page' => 2, /* <-- get both */
        'post_type'     => 'testimonial',
        'post_status'   => 'published',
        'orderby'   => 'rand',
        'ignore_sticky_posts' => true
      ));
    }
    return static::$testimonials;
  }

  function loop() {
    $testimonials = self::get_testimonials();
    if ($testimonials->have_posts()) {
      while($testimonials->have_posts()) {
        $testimonials->the_post();
        the_title();
        // whatever you need to do with the post content
        break; // stop the Loop; no complex logic needed since you are printing on and moving on
      }
    }
  }

}

Testimonial_Loop::loop();
Testimonial_Loop::loop();

And a third solution using a function and a static variable:

function testimonial_loop() {
  static $testimonials = false;

  if (empty($testimonials)) {
    $testimonials = new WP_Query(array(
      'posts_per_page' => 2, /* <-- get both */
      'post_type'     => 'post',
      'post_status'   => 'published',
      'orderby'   => 'rand',
      'ignore_sticky_posts' => true
    ));
  }

  if ($testimonials->have_posts()) {
    while($testimonials->have_posts()) {
      $testimonials->the_post();
      // whatever you need to do with the post content
      break; // stop the Loop; no complex logic needed since you are printing on and moving on
    }
  }
}
testimonial_loop();
testimonial_loop();