You have few errors in your code. Below you can see how it should look like:
function cd_random_testimonial($atts) {
// EXAMPLE USAGE:
// [loop the_query="showposts=1&post_type=testimonials&orderby=rand"]
// Defaults
extract(shortcode_atts(array(
'the_query' => ''
), $atts));
// de-funkify query
$the_query = preg_replace('~�*([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $the_query);
$the_query = preg_replace('~�*([0-9]+);~e', 'chr(\\1)', $the_query);
// query is made
$my_query = new WP_Query( $the_query ); // use custom WP_Query instead of query_posts
// Reset and setup variables
$output="";
// the loop
if ( $my_query->have_posts() ) {
while ( $my_query->have_posts() ) {
$my_query->the_post();
// the_content outputs content and you want to return it; and it doesn't take post_id as argument... and you don't use this variable, so you can delete this line, I guess
// $testimonial = get_the_content();
$clientname = get_the_title(); // it doesn't take post_id as argument
// output all findings - CUSTOMIZE TO YOUR LIKING
$output .= '<blockquote><p class="quote">';
$output .= get_the_content(); // doesn't take argument
$output .= '</p><p class="right">~ ';
$output .= $clientname;
$output .= '</p></blockquote>';
}
} else {
$output="nothing found.";
}
wp_reset_postdata();
return $output;
}
add_shortcode("loop", "cd_random_testimonial");