Is it possible to "toggle software keyboard" via the code in UI test?

Tested in Xcode 10.3 & Xcode 11. The snippet below needs to be located in the app target (not the test bundle) — for instance, in AppDelegate.swift. It will disable any hardware keyboards from automatically connecting by setting any UIKeyboardInputMode's automaticHardwareLayout properties to nil.

🔥 Does not depend on the settings of the Simulator.

#if targetEnvironment(simulator)
// Disable hardware keyboards.
let setHardwareLayout = NSSelectorFromString("setHardwareLayout:")
UITextInputMode.activeInputModes
    // Filter `UIKeyboardInputMode`s.
    .filter({ $0.responds(to: setHardwareLayout) })
    .forEach { $0.perform(setHardwareLayout, with: nil) }
#endif

Or Objective-C:

#if TARGET_IPHONE_SIMULATOR
SEL setHardwareLayout = NSSelectorFromString(@"setHardwareLayout:");
for (UITextInputMode *inputMode in [UITextInputMode activeInputModes]) {
    if ([inputMode respondsToSelector:setHardwareLayout]) {
        // Note: `performSelector:withObject:` will complain, so we have to use some black magic.
        ((void (*)(id, SEL, id))[inputMode methodForSelector:setHardwareLayout])(inputMode, setHardwareLayout, NULL);
    }
}
#endif

The simulator's .plist file changed to add support for multiple simulators. The ConnectHardwareKeyboard boolean is now nested underneath the device's UDID. Luckily this UDID is also stored in the plist file. You can add this code using 'run script' under your UITest target's build phases.

Xcode 9 answer:

#grab the UDID from the plist
UDID=$(defaults read com.apple.iphonesimulator CurrentDeviceUDID)

#overwrite the existing value with false
#OR if the plist doesn't have that value add it in
/usr/libexec/PlistBuddy -c "Set :DevicePreferences:$UDID:ConnectHardwareKeyboard 
false" ~/Library/Preferences/com.apple.iphonesimulator.plist 
|| 
/usr/libexec/PlistBuddy -c  "Add :DevicePreferences:$UDID:ConnectHardwareKeyboard
bool false" ~/Library/Preferences/com.apple.iphonesimulator.plist

Or you can use this other code to affect all simulators:

/usr/libexec/PlistBuddy -c "Print :DevicePreferences" ~/Library/Preferences/com.apple.iphonesimulator.plist | perl -lne 'print $1 if /^    (\S*) =/' | while read -r a; do /usr/libexec/PlistBuddy -c "Set :DevicePreferences:$a:ConnectHardwareKeyboard
false" ~/Library/Preferences/com.apple.iphonesimulator.plist || /usr/libexec/PlistBuddy -c  "Add :DevicePreferences:$a:ConnectHardwareKeyboard
bool false" ~/Library/Preferences/com.apple.iphonesimulator.plist; done

Prior to Xcode 9, you can work around this by disabling the hardware keyboard in Simulator.app which will cause the software keyboard to always be present. Eg:

defaults write com.apple.iphonesimulator ConnectHardwareKeyboard -bool NO

Following Brooks great answer, this will work for all simulators:

/usr/libexec/PlistBuddy -c "Print :DevicePreferences" ~/Library/Preferences/com.apple.iphonesimulator.plist | perl -lne 'print $1 if /^    (\S*) =/' | while read -r a; do /usr/libexec/PlistBuddy -c "Set :DevicePreferences:$a:ConnectHardwareKeyboard
false" ~/Library/Preferences/com.apple.iphonesimulator.plist || /usr/libexec/PlistBuddy -c  "Add :DevicePreferences:$a:ConnectHardwareKeyboard
bool false" ~/Library/Preferences/com.apple.iphonesimulator.plist; done