./test.sh runs test.sh as a separate program. It may happen to be a bash script, if the file test.sh starts with #!/bin/bash. But it could be something else altogether.
. ./test.sh execute the code of the file test.sh inside the running instance of bash. It works as if the content file test.sh had been included textually instead of the . ./test.sh line. (Almost: there are a few details that differ, such as the value of $BASH_LINENO, and the behavior of the return builtin.)
source ./test.sh is identical to . ./test.sh in bash (in other shells, source may be slightly different or not exist altogether; . for inclusion is in the POSIX standard).
The most commonly visible difference between running a separate script with ./test.sh and including a script with the . builtin is that if the test.sh script sets some environment variables, with a separate process, only the environment of the child process is set, whereas with script inclusion, the environment of the sole shell process is set. If you add a line foo=bar in test.sh and echo $foo at the end of the calling script, you'll see the difference:
$ cat test.sh
#!/bin/sh
foo=bar
$ ./test.sh
$ echo $foo
$ . ./test.sh
$ echo $foo
bar
test.shis not the same as./test.sh(the first invokes aPATHsearch), so are. test.shand. ./test.shdifferent in the same way (the former invokes aPATHsearch). Many shells seem to implicitly include.at the end ofPATHwhen doing a.path search, but this behavior is not standard. Thus, it is more accurate to comparetest.shvs. test.shand./test.shvs. ./test.sh. – jw013 Jul 30 '12 at 21:13