How to check for a specific string with linebreaks in a file with grep?

The problem is that grep will run on each line, not the entire file. As long as the file is small enough to fit into memory (which should be the case in the vast majority of situations these days), you can use grep's -z flag to slurp the entire file:

-z, --null-data Treat input and output data as sequences of lines, each terminated by a zero byte (the ASCII NUL character) instead of a newline. Like the -Z or --null option, this option can be used with commands like sort -z to process arbitrary file names.

The next issue, is that if you pass grep something with newlines, it will treat it as a list of patterns to grep for:

$ string="1
> 2"

$ seq 10 | grep "$string"
1
2
10
"

Which means that I am afraid you will have to express the pattern as a proper regular expression:

\n\ntest1\n\ntest2\n\n

However, this also means you need the -P flag to enable perl-compatible regular expressions so the \n will work.

I created these two files to demonstrate:

$ cat file1
this is a test:
test1

test2
and another one

$ cat file2
this is a test:

test1

test2

and another one

Using those two files and the information above, you can do:

$ grep -Pz '\n\ntest1\n\ntest2\n\n' file1
$ 

$ grep -Pz '\n\ntest1\n\ntest2\n\n' file2
this is a test:

test1

test2

and another one

Putting all this together gives us:

string='\n\ntest1\n\ntest2\n\n'
if ! grep -Pzq "$string" test.txt; then
    printf "$string" >> test.txt
fi

Or, as suggested by @steeldriver in a comment, you can use a variable and convert the newlines to \n on the fly:

$ string="

    test1

    test2

    "
$ if ! grep -Pzq "${string//$'\n'/\\n}" test.txt; then
    printf "$string" >> test.txt
fi

If your string contains special characters which have meanings in regular expressions, as you now show in your updated question, then that's a whole different situation. For the example you show, you would need something considerably more complicated. Like this:

searchString='\n\nif \[ -f ~/.script \]; then\s*\n\s*\.\s+~/\.script\s*\nfi\n\n'
printString='
if [ -f ~/.script ]; then
   . ~/.script         
fi

'
if ! grep -Pzq "$searchString" test.txt; then     
    printf "%s" "$printString" >> test.txt 
fi

You might want to consider using pcregrep with the -M or --multiline option to allow matching of literal newlines:

   -M, --multiline
             Allow patterns to match more than one line. When this  option
             is given, patterns may usefully contain literal newline char‐
             acters and internal occurrences of ^ and  $  characters.

Ex. given

$ cat test.txt
this is a test:
test1

test2
and another one


    test1

    test2
    
    

and

$ cat test2.txt
this is a test:
test1

test2
and another one


    test3

    test4
    
    

with

$ string="

    test1

    test2

    "

then

$ pcregrep -qM "$string" test.txt && echo 'found' || echo 'not found'
found

$ pcregrep -qM "$string" test2.txt && echo 'found' || echo 'not found'
not found