How to check if a role has a specific capability

#Update:
Wow, I feel like such a buffoon… haha. WP_Role::has_cap

I can’t (role) my eyes hard enough.

$caps  = array( 'cap_1', 'cap_2', 'cap_3' );
$roles = array( 'administrator', 'editor' );

foreach( $roles as $role ) {
    if( $role_object = get_role( $role ) ) {
        foreach( $caps as $cap ) {
            if( !$role_object->has_cap( $cap ) ) {
                $role_object->add_cap( $cap );
            }
        }
    }
}

#Disregard this nonesense:
I apologize, my other answer was per user not per role.

What you can do is check to see if the role has the capability using get_role()

You can see that get_role( 'administrator' ) will return an Object that has an array of capabilities in it.

$administrator = get_role( 'administrator' );

// Make sure role object was retrieved
if( $administrator ){
    //See if it's got our capability or not
    if( !in_array( 'my-custom-cap', $administrator->capabilities ) ){
        // Wasn't there, so add it here
        $administrator->add_cap( 'my-custom-cap' );
    }
}

If for some reason you don’t want to run the $role object comparison each time, you can define it once and then set a flag in the database with update_option() and check it with get_option()

if( get_option( 'manually_set_add_cap_admin' ) != true ){
    $administrator = get_role( 'administrator' );

    // Make sure role object was retrieved
    if( $administrator ){
        //See if it's got our capability or not
        if( !in_array( 'my-custom-cap', $administrator->capabilities ) ){
            // Wasn't there, so add it here
            $administrator->add_cap( 'my-custom-cap' );
            update_option( 'manually_set_add_cap_admin', true );
        }
    }
}

Here’s a bit more lengthy solution that will loop through any roles you add, and give them all the appropriate capabilities. After the loops are completed, it will set a flag that’s checked, so there won’t be any WP_Role object fetching after it’s ran the first time.

// Define flag as a variable to prevent typos, in update/get_option
// or it will constantly run (I know from experience...)
$flag = 'manually_added_my_custom_caps';

if( !get_option( $flag ) ){
    // Our flag option wasn't set, that means this code hasn't run yet.

    $roles        = array( 'administrator', 'editor' );
    $capabilities = array( 'custom-cap-1', 'custom-cap-2' );

    // Loop through each role
    foreach( $roles as $role ){
        // Make sure we got a WP_Role object back
        if( $role_object = get_role( $role ) ){
            // Loop through our custom capabilities
            foreach( $capabilities as $cap ){
                // Our option flag wasn't set, but let's confirm
                // that the role doesn't have the cap
                if( !in_array( $cap, $role_object->capabilities ) ){
                    // Confirmed not there, add it here
                    $role_object->add_cap( $cap );
                }
            }
        }
    }

    // Our function ran, it should have set all caps to all the roles
    // so now our code will skip this entirely next time
    update_option( $flag, true );
}