count is the right way to do this. For the common case of checking whether there are any arguments, you can use its exit status:
function fcd
if count $argv > /dev/null
open $argv
else
open $PWD
end
end
To answer your second question, test -d $argv returns true if $argv is empty, because POSIX requires that when test is passed one argument, it must “Exit true (0) if $1 is not null; otherwise, exit false”. So when $argv is empty, test -d $argv means test -d which must exit true because -d is not empty! Argh!
edit Added a missing end, thanks to Ismail for noticing