code: def test_avail_actions_qmix(self):
      grouping = {
          "group_1": ["agent_1", "agent_2"],
      }
      obs_space = Tuple(
          [
              AvailActionsTestEnv.observation_space,
              AvailActionsTestEnv.observation_space,
          ]
      )
      act_space = Tuple(
          [
              AvailActionsTestEnv.action_space,
              AvailActionsTestEnv.action_space,
          ]
      )
      register_env(
          "action_mask_test",
          lambda config: AvailActionsTestEnv(config).with_agent_groups(
              grouping, obs_space=obs_space, act_space=act_space
          ),
      )
  
      config = (
          QMixConfig()
          .framework(framework="torch")
          .environment(
              env="action_mask_test",
              env_config={"avail_actions": [3, 4, 8]},
          )
          .rollouts(num_envs_per_worker=5)
      )  # Test with vectorization on.
  
      algo = config.build()
  
      for _ in range(4):
          algo.train()  # OK if it doesn't trip the action assertion error
  
      assert algo.train()["episode_reward_mean"] == 30.0
      algo.stop()
      ray.shutdown()
  
file_path: ray/rllib_contrib/qmix/tests/test_qmix.py
imports: import unittest
  import numpy
  from gymnasium.spaces import Box, Dict, Discrete, MultiDiscrete, Tuple
  from rllib_qmix.qmix import QMixConfig
  import ray
  from ray.rllib.env.multi_agent_env import MultiAgentEnv
  from ray.tune import register_env
label_desc: Use image node_id 3 for calling the TestQMix obj's underlying member method code with example usage: obj.test_avail_actions_qmix() without return types