How to correctly merge two objects in blender
Need to set the active object.

The issue here is that operators work on the context.object to set an object to "active state" use both 

in 2.7x

context.scene.objects.active = ob0
ob0.select = True  


in 2.80

context.view_layer.objects.active = ob0
ob0.select_set(True)


Then when you run an operator it sees ob0 as context.

Just setting ob0.select = True is not #selecting obj0 so the bpy modifier is constructed for it

Without the above, because you added ob1 last, it was still context.object and hence you were trying to set its union object to itself.

An object can be active but not selected, selected but not active.

Again from  a previous answer https://blender.stackexchange.com/a/133292/15543 I showed how to add a modifier using api methods to get its reference IMO this is far simpler than using an operator. 

Surely

bool = ob0.modifiers.new(name='booly', type='BOOLEAN')
bool.object = ob1
bool.operation = 'UNION'


is more readable (, and simpler) than

bpy.ops.object.select_all(action='DESELECT')
bpy.context.scene.objects.active = obj0
obj0.select = True 
bpy.ops.object.modifier_add(type='BOOLEAN')
bpy.context.object.modifiers["Boolean"].object = obj1
bpy.context.object.modifiers["Boolean"].operation = 'UNION'


Soapbox TLDR:

Recommend getting out of the habit of always addressing via bpy.context.foo.bar.blah  For example in test code if the line context = bpy.context is added at the top, removes the need to use bpy.context.... every bloody time, if later we choose to copy paste our code into operators or panels then the context matches the argument context  in draw and execute methods etc. 

Or after adding modifier with operator

bpy.ops.object.modifier_add(type='BOOLEAN')  
mod = obj0.modifiers[-1] # it's the last added
mod.object = obj1
mod.operation = 'UNION'


Here I've referred to the newly created modifier as a variable  "mod",  over obj0.modifiers["Boolean"] and definitely rather than the long winded bpy.context.object.modifiers["Boolean"]