Testing Terminal Text Game with Classes and Game Loop
You already have the answer to your "bug" given in the comments, but I will try to give you a more in-depth review. Nevertheless, I will repeat the aforementioned solution: to avoid the program auto-running on import, but your main call inside of a if __name__ == "__main__" (read more here if interested).

For your __init__ method, having your method initializers as (default) arguments tend to give more flexibility down the road as the project grows:

    def __init__(self, castle=1, villagers=1, warriors=0, food=0, stone=0):
        self.castle = castle
        self.villagers = villagers
        self.warriors = warriors
        self.food = food
        self.stone = stone


For your first real method, I would recommend staying with the Python standard of snake_case over camelCase. Furthermore, initialising the variable action to 0 doesn't really do you anything since you overwrite it in the following line. And since you rely on that input I think you should figure out what to do when you don't get an int, or if you get something like 11 (because 11 here would likely be a typo, given the options).

This, quite naturally, leads on to the purpose of testing (yay!). A nice thing about tests is that they allow you to think about what exactly you want to happen when you create an object or call on a function. For your takeTurns function, that would maybe be that you're only allowed to enter digits, and if you don't enter a single digit in the range 0–5 it throws an exception or it asks for another input. You would then basically implement your function (after the tests) to meet all the requirements you set forth in the beginning. You may then also find that maybe you were thinking about it the wrong way; in this case it could be that maybe take_turns (I renamed it for you...) shouldn't be asking for input() but rather be accepting an argument take_turns(user_choice).

To finalise, I'll add some smaller pieces of advice.


Instead of self.__class__.__name__ == "Player": you could (and should) use isinstance(self, Player).
Instead of action = random.randint(1, 4) coupled with 4 if-statements, there's a handy little function in random called choice (have a look here). You could also make your AI class much smaller by rethinking how the AI differs (or doesn't differ) from a Player.
f-strings are super nice. Instead of print("You:\nCastle: " + str(player.castle) + " Food: " + str(player.food) + " Stone: " + str(player.stone) + " Villagers: " + str(player.villagers) + " Warriors: " + str(player.warriors) + "\n"), you could have (and notice that I removed str() since you don't need it):

print(f"""You:
Castle: {player.castle}
Food: {player.food}
Stone: {player.stone}
Villagers: {player.villagers}
Warriors: {player.warriors}""")