Merge "Move the `attr` decorator from test.py to tempest/lib"
diff --git a/releasenotes/notes/move-attr-decorator-to-lib-a1e80c42ba9c5392.yaml b/releasenotes/notes/move-attr-decorator-to-lib-a1e80c42ba9c5392.yaml
new file mode 100644
index 0000000..58d45cc
--- /dev/null
+++ b/releasenotes/notes/move-attr-decorator-to-lib-a1e80c42ba9c5392.yaml
@@ -0,0 +1,6 @@
+---
+features:
+  - |
+    A new ``attr`` decorator has been added in the ``tempest.lib.decorators``
+    module. For example, use it to tag specific tests, which could be leveraged
+    by test runners to run only a subset of Tempest tests.
diff --git a/tempest/api/compute/admin/test_aggregates_negative.py b/tempest/api/compute/admin/test_aggregates_negative.py
index e682570..69689a7 100644
--- a/tempest/api/compute/admin/test_aggregates_negative.py
+++ b/tempest/api/compute/admin/test_aggregates_negative.py
@@ -18,7 +18,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class AggregatesAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -47,7 +46,7 @@
         self.addCleanup(self.client.delete_aggregate, aggregate['id'])
         return aggregate
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('86a1cb14-da37-4a70-b056-903fd56dfe29')
     def test_aggregate_create_as_user(self):
         # Regular user is not allowed to create an aggregate.
@@ -56,7 +55,7 @@
                           self.user_client.create_aggregate,
                           name=aggregate_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3b8a1929-3793-4e92-bcb4-dfa572ee6c1d')
     def test_aggregate_create_aggregate_name_length_less_than_1(self):
         # the length of aggregate name should >= 1 and <=255
@@ -64,7 +63,7 @@
                           self.client.create_aggregate,
                           name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4c194563-543b-4e70-a719-557bbe947fac')
     def test_aggregate_create_aggregate_name_length_exceeds_255(self):
         # the length of aggregate name should >= 1 and <=255
@@ -73,7 +72,7 @@
                           self.client.create_aggregate,
                           name=aggregate_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9c23a291-b0b1-487b-b464-132e061151b3')
     def test_aggregate_create_with_existent_aggregate_name(self):
         # creating an aggregate with existent aggregate name is forbidden
@@ -82,7 +81,7 @@
                           self.client.create_aggregate,
                           name=aggregate['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('cd6de795-c15d-45f1-8d9e-813c6bb72a3d')
     def test_aggregate_delete_as_user(self):
         # Regular user is not allowed to delete an aggregate.
@@ -91,14 +90,14 @@
                           self.user_client.delete_aggregate,
                           aggregate['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b7d475a6-5dcd-4ff4-b70a-cd9de66a6672')
     def test_aggregate_list_as_user(self):
         # Regular user is not allowed to list aggregates.
         self.assertRaises(lib_exc.Forbidden,
                           self.user_client.list_aggregates)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('557cad12-34c9-4ff4-95f0-22f0dfbaf7dc')
     def test_aggregate_get_details_as_user(self):
         # Regular user is not allowed to get aggregate details.
@@ -107,21 +106,21 @@
                           self.user_client.show_aggregate,
                           aggregate['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c74f4bf1-4708-4ff2-95a0-f49eaca951bd')
     def test_aggregate_delete_with_invalid_id(self):
         # Delete an aggregate with invalid id should raise exceptions.
         self.assertRaises(lib_exc.NotFound,
                           self.client.delete_aggregate, -1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3c916244-2c46-49a4-9b55-b20bb0ae512c')
     def test_aggregate_get_details_with_invalid_id(self):
         # Get aggregate details with invalid id should raise exceptions.
         self.assertRaises(lib_exc.NotFound,
                           self.client.show_aggregate, -1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0ef07828-12b4-45ba-87cc-41425faf5711')
     def test_aggregate_add_non_exist_host(self):
         # Adding a non-exist host to an aggregate should raise exceptions.
@@ -135,7 +134,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.add_host,
                           aggregate['id'], host=non_exist_host)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7324c334-bd13-4c93-8521-5877322c3d51')
     def test_aggregate_add_host_as_user(self):
         # Regular user is not allowed to add a host to an aggregate.
@@ -144,7 +143,7 @@
                           self.user_client.add_host,
                           aggregate['id'], host=self.host)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('19dd44e1-c435-4ee1-a402-88c4f90b5950')
     def test_aggregate_add_existent_host(self):
         self.useFixture(fixtures.LockFixture('availability_zone'))
@@ -157,7 +156,7 @@
         self.assertRaises(lib_exc.Conflict, self.client.add_host,
                           aggregate['id'], host=self.host)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7a53af20-137a-4e44-a4ae-e19260e626d9')
     def test_aggregate_remove_host_as_user(self):
         # Regular user is not allowed to remove a host from an aggregate.
@@ -172,7 +171,7 @@
                           self.user_client.remove_host,
                           aggregate['id'], host=self.host)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('95d6a6fa-8da9-4426-84d0-eec0329f2e4d')
     def test_aggregate_remove_nonexistent_host(self):
         aggregate = self._create_test_aggregate()
diff --git a/tempest/api/compute/admin/test_availability_zone_negative.py b/tempest/api/compute/admin/test_availability_zone_negative.py
index faeb811..a58c22c 100644
--- a/tempest/api/compute/admin/test_availability_zone_negative.py
+++ b/tempest/api/compute/admin/test_availability_zone_negative.py
@@ -15,7 +15,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class AZAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -26,7 +25,7 @@
         super(AZAdminNegativeTestJSON, cls).setup_clients()
         cls.non_adm_client = cls.availability_zone_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bf34dca2-fdc3-4073-9c02-7648d9eae0d7')
     def test_get_availability_zone_list_detail_with_non_admin_user(self):
         # List of availability zones and available services with
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
index 073f152..5134b81 100644
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ b/tempest/api/compute/admin/test_fixed_ips_negative.py
@@ -49,14 +49,14 @@
             if cls.ip:
                 break
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9f17f47d-daad-4adc-986e-12370c93e407')
     @test.services('network')
     def test_list_fixed_ip_details_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.show_fixed_ip, self.ip)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ce60042c-fa60-4836-8d43-1c8e3359dc47')
     @test.services('network')
     def test_set_reserve_with_non_admin_user(self):
@@ -64,7 +64,7 @@
                           self.non_admin_client.reserve_fixed_ip,
                           self.ip, reserve="None")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f1f7a35b-0390-48c5-9803-5f27461439db')
     @test.services('network')
     def test_set_unreserve_with_non_admin_user(self):
@@ -72,7 +72,7 @@
                           self.non_admin_client.reserve_fixed_ip,
                           self.ip, unreserve="None")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f51cf464-7fc5-4352-bc3e-e75cfa2cb717')
     @test.services('network')
     def test_set_reserve_with_invalid_ip(self):
@@ -85,7 +85,7 @@
                           self.client.reserve_fixed_ip,
                           "my.invalid.ip", reserve="None")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fd26ef50-f135-4232-9d32-281aab3f9176')
     @test.services('network')
     def test_fixed_ip_with_invalid_action(self):
diff --git a/tempest/api/compute/admin/test_flavors_access_negative.py b/tempest/api/compute/admin/test_flavors_access_negative.py
index 12e4587..be165cb 100644
--- a/tempest/api/compute/admin/test_flavors_access_negative.py
+++ b/tempest/api/compute/admin/test_flavors_access_negative.py
@@ -43,7 +43,7 @@
         cls.vcpus = 1
         cls.disk = 10
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0621c53e-d45d-40e7-951d-43e5e257b272')
     def test_flavor_access_list_with_public_flavor(self):
         # Test to list flavor access with exceptions by querying public flavor
@@ -53,7 +53,7 @@
                           self.admin_flavors_client.list_flavor_access,
                           flavor['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('41eaaade-6d37-4f28-9c74-f21b46ca67bd')
     def test_flavor_non_admin_add(self):
         # Test to add flavor access as a user without admin privileges.
@@ -64,7 +64,7 @@
                           flavor['id'],
                           self.tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('073e79a6-c311-4525-82dc-6083d919cb3a')
     def test_flavor_non_admin_remove(self):
         # Test to remove flavor access as a user without admin privileges.
@@ -81,7 +81,7 @@
                           flavor['id'],
                           self.tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f3592cc0-0306-483c-b210-9a7b5346eddc')
     def test_add_flavor_access_duplicate(self):
         # Create a new flavor.
@@ -101,7 +101,7 @@
                           flavor['id'],
                           self.tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1f710927-3bc7-4381-9f82-0ca6e42644b7')
     def test_remove_flavor_access_not_found(self):
         # Create a new flavor.
diff --git a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
index a728711..f39feb9 100644
--- a/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
+++ b/tempest/api/compute/admin/test_flavors_extra_specs_negative.py
@@ -62,7 +62,7 @@
         cls.admin_flavors_client.wait_for_resource_deletion(cls.flavor['id'])
         super(FlavorsExtraSpecsNegativeTestJSON, cls).resource_cleanup()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a00a3b81-5641-45a8-ab2b-4a8ec41e1d7d')
     def test_flavor_non_admin_set_keys(self):
         # Test to SET flavor extra spec as a user without admin privileges.
@@ -71,7 +71,7 @@
                           self.flavor['id'],
                           key1="value1", key2="value2")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1ebf4ef8-759e-48fe-a801-d451d80476fb')
     def test_flavor_non_admin_update_specific_key(self):
         # non admin user is not allowed to update flavor extra spec
@@ -85,7 +85,7 @@
                           'key1',
                           key1='value1_new')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('28f12249-27c7-44c1-8810-1f382f316b11')
     def test_flavor_non_admin_unset_keys(self):
         self.admin_flavors_client.set_flavor_extra_spec(
@@ -96,7 +96,7 @@
                           self.flavor['id'],
                           'key1')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('440b9f3f-3c7f-4293-a106-0ceda350f8de')
     def test_flavor_unset_nonexistent_key(self):
         self.assertRaises(lib_exc.NotFound,
@@ -104,7 +104,7 @@
                           self.flavor['id'],
                           'nonexistent_key')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('329a7be3-54b2-48be-8052-bf2ce4afd898')
     def test_flavor_get_nonexistent_key(self):
         self.assertRaises(lib_exc.NotFound,
@@ -112,7 +112,7 @@
                           self.flavor['id'],
                           "nonexistent_key")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('25b822b8-9f49-44f6-80de-d99f0482e5cb')
     def test_flavor_update_mismatch_key(self):
         # the key will be updated should be match the key in the body
@@ -122,7 +122,7 @@
                           "key2",
                           key1="value")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f5889590-bf66-41cc-b4b1-6e6370cfd93f')
     def test_flavor_update_more_key(self):
         # there should be just one item in the request body
diff --git a/tempest/api/compute/admin/test_hosts_negative.py b/tempest/api/compute/admin/test_hosts_negative.py
index 07ab8c5..684f656 100644
--- a/tempest/api/compute/admin/test_hosts_negative.py
+++ b/tempest/api/compute/admin/test_hosts_negative.py
@@ -15,7 +15,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class HostsAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -35,26 +34,26 @@
             raise lib_exc.NotFound("no host found")
         cls.hostname = hosts[0]['host_name']
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('dd032027-0210-4d9c-860e-69b1b8deed5f')
     def test_list_hosts_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.list_hosts)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e75b0a1a-041f-47a1-8b4a-b72a6ff36d3f')
     def test_show_host_detail_with_nonexistent_hostname(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.show_host, 'nonexistent_hostname')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('19ebe09c-bfd4-4b7c-81a2-e2e0710f59cc')
     def test_show_host_detail_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.show_host,
                           self.hostname)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e40c72b1-0239-4ed6-ba21-81a184df1f7c')
     def test_update_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
@@ -63,7 +62,7 @@
                           status='enable',
                           maintenance_mode='enable')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fbe2bf3e-3246-4a95-a59f-94e4e298ec77')
     def test_update_host_with_invalid_status(self):
         # 'status' can only be 'enable' or 'disable'
@@ -73,7 +72,7 @@
                           status='invalid',
                           maintenance_mode='enable')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ab1e230e-5e22-41a9-8699-82b9947915d4')
     def test_update_host_with_invalid_maintenance_mode(self):
         # 'maintenance_mode' can only be 'enable' or 'disable'
@@ -83,7 +82,7 @@
                           status='enable',
                           maintenance_mode='invalid')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0cd85f75-6992-4a4a-b1bd-d11e37fd0eee')
     def test_update_host_without_param(self):
         # 'status' or 'maintenance_mode' needed for host update
@@ -91,7 +90,7 @@
                           self.client.update_host,
                           self.hostname)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('23c92146-2100-4d68-b2d6-c7ade970c9c1')
     def test_update_nonexistent_host(self):
         self.assertRaises(lib_exc.NotFound,
@@ -100,42 +99,42 @@
                           status='enable',
                           maintenance_mode='enable')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0d981ac3-4320-4898-b674-82b61fbb60e4')
     def test_startup_nonexistent_host(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.startup_host,
                           'nonexistent_hostname')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9f4ebb7e-b2ae-4e5b-a38f-0fd1bb0ddfca')
     def test_startup_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.startup_host,
                           self.hostname)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9e637444-29cf-4244-88c8-831ae82c31b6')
     def test_shutdown_nonexistent_host(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.shutdown_host,
                           'nonexistent_hostname')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a803529c-7e3f-4d3c-a7d6-8e1c203d27f6')
     def test_shutdown_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.shutdown_host,
                           self.hostname)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f86bfd7b-0b13-4849-ae29-0322e83ee58b')
     def test_reboot_nonexistent_host(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.reboot_host,
                           'nonexistent_hostname')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('02d79bb9-eb57-4612-abf6-2cb38897d2f8')
     def test_reboot_host_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
diff --git a/tempest/api/compute/admin/test_hypervisor_negative.py b/tempest/api/compute/admin/test_hypervisor_negative.py
index b8a67b9..2addce9 100644
--- a/tempest/api/compute/admin/test_hypervisor_negative.py
+++ b/tempest/api/compute/admin/test_hypervisor_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class HypervisorAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -34,7 +33,7 @@
         hypers = self.client.list_hypervisors()['hypervisors']
         return hypers
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c136086a-0f67-4b2b-bc61-8482bd68989f')
     def test_show_nonexistent_hypervisor(self):
         nonexistent_hypervisor_id = data_utils.rand_uuid()
@@ -44,7 +43,7 @@
             self.client.show_hypervisor,
             nonexistent_hypervisor_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('51e663d0-6b89-4817-a465-20aca0667d03')
     def test_show_hypervisor_with_non_admin_user(self):
         hypers = self._list_hypervisors()
@@ -55,7 +54,7 @@
             self.non_adm_client.show_hypervisor,
             hypers[0]['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('2a0a3938-832e-4859-95bf-1c57c236b924')
     def test_show_servers_with_non_admin_user(self):
         hypers = self._list_hypervisors()
@@ -66,7 +65,7 @@
             self.non_adm_client.list_servers_on_hypervisor,
             hypers[0]['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('02463d69-0ace-4d33-a4a8-93d7883a2bba')
     def test_show_servers_with_nonexistent_hypervisor(self):
         nonexistent_hypervisor_id = data_utils.rand_uuid()
@@ -76,14 +75,14 @@
             self.client.list_servers_on_hypervisor,
             nonexistent_hypervisor_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e2b061bb-13f9-40d8-9d6e-d5bf17595849')
     def test_get_hypervisor_stats_with_non_admin_user(self):
         self.assertRaises(
             lib_exc.Forbidden,
             self.non_adm_client.show_hypervisor_statistics)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f60aa680-9a3a-4c7d-90e1-fae3a4891303')
     def test_get_nonexistent_hypervisor_uptime(self):
         nonexistent_hypervisor_id = data_utils.rand_uuid()
@@ -93,7 +92,7 @@
             self.client.show_hypervisor_uptime,
             nonexistent_hypervisor_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6c3461f9-c04c-4e2a-bebb-71dc9cb47df2')
     def test_get_hypervisor_uptime_with_non_admin_user(self):
         hypers = self._list_hypervisors()
@@ -104,7 +103,7 @@
             self.non_adm_client.show_hypervisor_uptime,
             hypers[0]['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('51b3d536-9b14-409c-9bce-c6f7c794994e')
     def test_get_hypervisor_list_with_non_admin_user(self):
         # List of hypervisor and available services with non admin user
@@ -112,7 +111,7 @@
             lib_exc.Forbidden,
             self.non_adm_client.list_hypervisors)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('dc02db05-e801-4c5f-bc8e-d915290ab345')
     def test_get_hypervisor_list_details_with_non_admin_user(self):
         # List of hypervisor details and available services with non admin user
@@ -120,7 +119,7 @@
             lib_exc.Forbidden,
             self.non_adm_client.list_hypervisors, detail=True)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('19a45cc1-1000-4055-b6d2-28e8b2ec4faa')
     def test_search_nonexistent_hypervisor(self):
         self.assertRaises(
@@ -128,7 +127,7 @@
             self.client.search_hypervisor,
             'nonexistent_hypervisor_name')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5b6a6c79-5dc1-4fa5-9c58-9c8085948e74')
     def test_search_hypervisor_with_non_admin_user(self):
         hypers = self._list_hypervisors()
diff --git a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
index 16c39c4..92235cc 100644
--- a/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
+++ b/tempest/api/compute/admin/test_instance_usage_audit_log_negative.py
@@ -20,7 +20,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class InstanceUsageAuditLogNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -30,7 +29,7 @@
         super(InstanceUsageAuditLogNegativeTestJSON, cls).setup_clients()
         cls.adm_client = cls.os_adm.instance_usages_audit_log_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a9d33178-d2c9-4131-ad3b-f4ca8d0308a2')
     def test_instance_usage_audit_logs_with_nonadmin_user(self):
         # the instance_usage_audit_logs API just can be accessed by admin user
@@ -43,7 +42,7 @@
                           show_instance_usage_audit_log,
                           urllib.quote(now.strftime("%Y-%m-%d %H:%M:%S")))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9b952047-3641-41c7-ba91-a809fc5974c8')
     def test_get_instance_usage_audit_logs_with_invalid_time(self):
         self.assertRaises(lib_exc.BadRequest,
diff --git a/tempest/api/compute/admin/test_quotas_negative.py b/tempest/api/compute/admin/test_quotas_negative.py
index a1dd2e7..cc4654d 100644
--- a/tempest/api/compute/admin/test_quotas_negative.py
+++ b/tempest/api/compute/admin/test_quotas_negative.py
@@ -51,7 +51,7 @@
         self.addCleanup(self.adm_client.update_quota_set, self.demo_tenant_id,
                         **{quota_item: default_quota_value})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('733abfe8-166e-47bb-8363-23dbd7ff3476')
     def test_update_quota_normal_user(self):
         self.assertRaises(lib_exc.Forbidden,
@@ -61,7 +61,7 @@
 
     # TODO(afazekas): Add dedicated tenant to the skipped quota tests.
     # It can be moved into the setUpClass as well.
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('91058876-9947-4807-9f22-f6eb17140d9b')
     def test_create_server_when_cpu_quota_is_full(self):
         # Disallow server creation when tenant's vcpu quota is full
@@ -69,7 +69,7 @@
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6fdd7012-584d-4327-a61c-49122e0d5864')
     def test_create_server_when_memory_quota_is_full(self):
         # Disallow server creation when tenant's memory quota is full
@@ -77,7 +77,7 @@
         self.assertRaises((lib_exc.Forbidden, lib_exc.OverLimit),
                           self.create_test_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7c6be468-0274-449a-81c3-ac1c32ee0161')
     def test_create_server_when_instances_quota_is_full(self):
         # Once instances quota limit is reached, disallow server creation
@@ -87,7 +87,7 @@
 
     @decorators.skip_because(bug="1186354",
                              condition=CONF.service_available.neutron)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7c6c8f3b-2bf6-4918-b240-57b136a66aa0')
     @test.services('network')
     def test_security_groups_exceed_limit(self):
@@ -106,7 +106,7 @@
 
     @decorators.skip_because(bug="1186354",
                              condition=CONF.service_available.neutron)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6e9f436d-f1ed-4f8e-a493-7275dfaa4b4d')
     @test.services('network')
     def test_security_groups_rules_exceed_limit(self):
diff --git a/tempest/api/compute/admin/test_servers_negative.py b/tempest/api/compute/admin/test_servers_negative.py
index ebdceef..677972e 100644
--- a/tempest/api/compute/admin/test_servers_negative.py
+++ b/tempest/api/compute/admin/test_servers_negative.py
@@ -21,7 +21,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -47,7 +46,7 @@
     @decorators.idempotent_id('28dcec23-f807-49da-822c-56a92ea3c687')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_server_using_overlimit_ram(self):
         # NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
         self.useFixture(fixtures.LockFixture('compute_quotas'))
@@ -69,7 +68,7 @@
     @decorators.idempotent_id('7368a427-2f26-4ad9-9ba9-911a0ec2b0db')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_server_using_overlimit_vcpus(self):
         # NOTE(mriedem): Avoid conflicts with os-quota-class-sets tests.
         self.useFixture(fixtures.LockFixture('compute_quotas'))
@@ -88,27 +87,27 @@
                           self.servers[0]['id'],
                           flavor_ref['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b0b4d8af-1256-41ef-9ee7-25f1c19dde80')
     def test_reset_state_server_invalid_state(self):
         self.assertRaises(lib_exc.BadRequest,
                           self.client.reset_state, self.s1_id,
                           state='invalid')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4cdcc984-fab0-4577-9a9d-6d558527ee9d')
     def test_reset_state_server_invalid_type(self):
         self.assertRaises(lib_exc.BadRequest,
                           self.client.reset_state, self.s1_id,
                           state=1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e741298b-8df2-46f0-81cb-8f814ff2504c')
     def test_reset_state_server_nonexistent_server(self):
         self.assertRaises(lib_exc.NotFound,
                           self.client.reset_state, '999', state='error')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e84e2234-60d2-42fa-8b30-e2d3049724ac')
     def test_get_server_diagnostics_by_non_admin(self):
         # Non-admin user can not view server diagnostics according to policy
@@ -116,7 +115,7 @@
                           self.non_adm_client.show_server_diagnostics,
                           self.s1_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('46a4e1ca-87ae-4d28-987a-1b6b136a0221')
     def test_migrate_non_existent_server(self):
         # migrate a non existent server
@@ -129,7 +128,7 @@
                           'Resize not available.')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_migrate_server_invalid_state(self):
         # create server.
         server = self.create_test_server(wait_until='ACTIVE')
diff --git a/tempest/api/compute/admin/test_services_negative.py b/tempest/api/compute/admin/test_services_negative.py
index 9447a09..1edfc89 100644
--- a/tempest/api/compute/admin/test_services_negative.py
+++ b/tempest/api/compute/admin/test_services_negative.py
@@ -15,7 +15,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ServicesAdminNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -27,13 +26,13 @@
         cls.client = cls.os_adm.services_client
         cls.non_admin_client = cls.services_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1126d1f8-266e-485f-a687-adc547492646')
     def test_list_services_with_non_admin_user(self):
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_client.list_services)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d0884a69-f693-4e79-a9af-232d15643bf7')
     def test_get_service_by_invalid_params(self):
         # return all services if send the request with invalid parameter
@@ -42,7 +41,7 @@
                         ['services'])
         self.assertEqual(len(services), len(services_xxx))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1e966d4a-226e-47c7-b601-0b18a27add54')
     def test_get_service_by_invalid_service_and_valid_host(self):
         services = self.client.list_services()['services']
@@ -51,7 +50,7 @@
                                              binary='xxx')['services']
         self.assertEqual(0, len(services))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('64e7e7fb-69e8-4cb6-a71d-8d5eb0c98655')
     def test_get_service_with_valid_service_and_invalid_host(self):
         services = self.client.list_services()['services']
diff --git a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
index 35762d6..222d28c 100644
--- a/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
+++ b/tempest/api/compute/admin/test_simple_tenant_usage_negative.py
@@ -18,7 +18,6 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class TenantUsagesNegativeTestJSON(base.BaseV2ComputeAdminTest):
@@ -41,7 +40,7 @@
         # Returns formatted datetime
         return at.strftime('%Y-%m-%dT%H:%M:%S.%f')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8b21e135-d94b-4991-b6e9-87059609c8ed')
     def test_get_usage_tenant_with_empty_tenant_id(self):
         # Get usage for a specific tenant empty
@@ -51,7 +50,7 @@
                           self.adm_client.show_tenant_usage,
                           '', **params)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4079dd2a-9e8d-479f-869d-6fa985ce45b6')
     def test_get_usage_tenant_with_invalid_date(self):
         # Get usage for tenant with invalid date
@@ -61,7 +60,7 @@
                           self.adm_client.show_tenant_usage,
                           self.client.tenant_id, **params)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bbe6fe2c-15d8-404c-a0a2-44fad0ad5cc7')
     def test_list_usage_all_tenants_with_non_admin_user(self):
         # Get usage for all tenants with non admin user
diff --git a/tempest/api/compute/admin/test_volumes_negative.py b/tempest/api/compute/admin/test_volumes_negative.py
index 7ebd074..4a7f36f 100644
--- a/tempest/api/compute/admin/test_volumes_negative.py
+++ b/tempest/api/compute/admin/test_volumes_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -36,7 +35,7 @@
         super(VolumesAdminNegativeTest, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('309b5ecd-0585-4a7e-a36f-d2b2bf55259d')
     def test_update_attached_volume_with_nonexistent_volume_in_uri(self):
         volume = self.create_volume()
@@ -47,7 +46,7 @@
                           volumeId=volume['id'])
 
     @decorators.related_bug('1629110', status_code=400)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7dcac15a-b107-46d3-a5f6-cb863f4e454a')
     def test_update_attached_volume_with_nonexistent_volume_in_body(self):
         volume = self.create_volume()
diff --git a/tempest/api/compute/flavors/test_flavors.py b/tempest/api/compute/flavors/test_flavors.py
index 89051c1..bf4c958 100644
--- a/tempest/api/compute/flavors/test_flavors.py
+++ b/tempest/api/compute/flavors/test_flavors.py
@@ -15,14 +15,13 @@
 
 from tempest.api.compute import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class FlavorsV2TestJSON(base.BaseV2ComputeTest):
     _min_disk = 'minDisk'
     _min_ram = 'minRam'
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('e36c0eaa-dff5-4082-ad1f-3f9a80aa3f59')
     def test_list_flavors(self):
         # List of all flavors should contain the expected flavor
@@ -39,7 +38,7 @@
         flavor = self.flavors_client.show_flavor(self.flavor_ref)['flavor']
         self.assertIn(flavor, flavors)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('1f12046b-753d-40d2-abb6-d8eb8b30cb2f')
     def test_get_flavor(self):
         # The expected flavor details should be returned
diff --git a/tempest/api/compute/flavors/test_flavors_negative.py b/tempest/api/compute/flavors/test_flavors_negative.py
index eee6bd2..b2c33e2 100644
--- a/tempest/api/compute/flavors/test_flavors_negative.py
+++ b/tempest/api/compute/flavors/test_flavors_negative.py
@@ -42,7 +42,7 @@
                 'Either api_v1 or api_v2 must be True in '
                 '[image-feature-enabled].')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @test.services('image')
     @decorators.idempotent_id('90f0d93a-91c1-450c-91e6-07d18172cefe')
     def test_boot_with_low_ram(self):
diff --git a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
index b3c3e17..cce9856 100644
--- a/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
+++ b/tempest/api/compute/floating_ips/test_floating_ips_actions_negative.py
@@ -48,7 +48,7 @@
             if cls.non_exist_id not in floating_ip_ids:
                 break
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6e0f059b-e4dd-48fb-8207-06e3bba5b074')
     @test.services('network')
     def test_allocate_floating_ip_from_nonexistent_pool(self):
@@ -58,7 +58,7 @@
                           self.client.create_floating_ip,
                           pool="non_exist_pool")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ae1c55a8-552b-44d4-bfb6-2a115a15d0ba')
     @test.services('network')
     def test_delete_nonexistent_floating_ip(self):
@@ -69,7 +69,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_floating_ip,
                           self.non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('595fa616-1a71-4670-9614-46564ac49a4c')
     @test.services('network')
     def test_associate_nonexistent_floating_ip(self):
@@ -80,7 +80,7 @@
                           self.client.associate_floating_ip_to_server,
                           "0.0.0.0", self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0a081a66-e568-4e6b-aa62-9587a876dca8')
     @test.services('network')
     def test_dissociate_nonexistent_floating_ip(self):
@@ -90,7 +90,7 @@
                           self.client.disassociate_floating_ip_from_server,
                           "0.0.0.0", self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('804b4fcb-bbf5-412f-925d-896672b61eb3')
     @test.services('network')
     def test_associate_ip_to_server_without_passing_floating_ip(self):
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
index 388db0b..9d70bf7 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips_negative.py
@@ -30,7 +30,7 @@
         super(FloatingIPDetailsNegativeTestJSON, cls).setup_clients()
         cls.client = cls.floating_ips_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7ab18834-4a4b-4f28-a2c5-440579866695')
     @test.services('network')
     def test_get_nonexistent_floating_ip_details(self):
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index 9cb4b57..03d0789 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ImagesMetadataNegativeTestJSON(base.BaseV2ComputeTest):
@@ -27,7 +26,7 @@
         super(ImagesMetadataNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('94069db2-792f-4fa8-8bd3-2271a6e0c095')
     def test_list_nonexistent_image_metadata(self):
         # Negative test: List on nonexistent image
@@ -35,7 +34,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.list_image_metadata,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a403ef9e-9f95-427c-b70a-3ce3388796f1')
     def test_update_nonexistent_image_metadata(self):
         # Negative test:An update should not happen for a non-existent image
@@ -44,7 +43,7 @@
                           self.client.update_image_metadata,
                           data_utils.rand_uuid(), meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('41ae052c-6ee6-405c-985e-5712393a620d')
     def test_get_nonexistent_image_metadata_item(self):
         # Negative test: Get on non-existent image should not happen
@@ -52,7 +51,7 @@
                           self.client.show_image_metadata_item,
                           data_utils.rand_uuid(), 'os_version')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('dc64f2ce-77e8-45b0-88c8-e15041d08eaf')
     def test_set_nonexistent_image_metadata(self):
         # Negative test: Metadata should not be set to a non-existent image
@@ -60,7 +59,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.set_image_metadata,
                           data_utils.rand_uuid(), meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('2154fd03-ab54-457c-8874-e6e3eb56e9cf')
     def test_set_nonexistent_image_metadata_item(self):
         # Negative test: Metadata item should not be set to a
@@ -71,7 +70,7 @@
                           data_utils.rand_uuid(), 'os_distro',
                           meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('848e157f-6bcf-4b2e-a5dd-5124025a8518')
     def test_delete_nonexistent_image_metadata_item(self):
         # Negative test: Shouldn't be able to delete metadata
diff --git a/tempest/api/compute/images/test_images_negative.py b/tempest/api/compute/images/test_images_negative.py
index 86013d4..e292389 100644
--- a/tempest/api/compute/images/test_images_negative.py
+++ b/tempest/api/compute/images/test_images_negative.py
@@ -18,7 +18,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -41,7 +40,7 @@
         super(ImagesNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6cd5a89d-5b47-46a7-93bc-3916f0d84973')
     def test_create_image_from_deleted_server(self):
         # An image should not be created if the server instance is removed
@@ -56,7 +55,7 @@
                           self.create_image_from_server,
                           server['id'], metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('82c5b0c4-9dbd-463c-872b-20c4755aae7f')
     def test_create_image_from_invalid_server(self):
         # An image should not be created with invalid server id
@@ -65,7 +64,7 @@
         self.assertRaises(lib_exc.NotFound, self.create_image_from_server,
                           data_utils.rand_name('invalid'), metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ec176029-73dc-4037-8d72-2e4ff60cf538')
     def test_create_image_specify_uuid_35_characters_or_less(self):
         # Return an error if Image ID passed is 35 characters or less
@@ -74,7 +73,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.create_image,
                           test_uuid, name=snapshot_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('36741560-510e-4cc2-8641-55fe4dfb2437')
     def test_create_image_specify_uuid_37_characters_or_more(self):
         # Return an error if Image ID passed is 37 characters or more
@@ -83,14 +82,14 @@
         self.assertRaises(lib_exc.NotFound, self.client.create_image,
                           test_uuid, name=snapshot_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('381acb65-785a-4942-94ce-d8f8c84f1f0f')
     def test_delete_image_with_invalid_image_id(self):
         # An image should not be deleted with invalid image id
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           data_utils.rand_name('invalid'))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('137aef61-39f7-44a1-8ddf-0adf82511701')
     def test_delete_non_existent_image(self):
         # Return an error while trying to delete a non-existent image
@@ -99,13 +98,13 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           non_existent_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e6e41425-af5c-4fe6-a4b5-7b7b963ffda5')
     def test_delete_image_blank_id(self):
         # Return an error while trying to delete an image with blank Id
         self.assertRaises(lib_exc.NotFound, self.client.delete_image, '')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('924540c3-f1f1-444c-8f58-718958b6724e')
     def test_delete_image_non_hex_string_id(self):
         # Return an error while trying to delete an image with non hex id
@@ -113,13 +112,13 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           invalid_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('68e2c175-bd26-4407-ac0f-4ea9ce2139ea')
     def test_delete_image_negative_image_id(self):
         # Return an error while trying to delete an image with negative id
         self.assertRaises(lib_exc.NotFound, self.client.delete_image, -1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b340030d-82cd-4066-a314-c72fb7c59277')
     def test_delete_image_with_id_over_character_limit(self):
         # Return an error while trying to delete image with id over limit
diff --git a/tempest/api/compute/images/test_images_oneserver_negative.py b/tempest/api/compute/images/test_images_oneserver_negative.py
index 68563bd..cf32ba3 100644
--- a/tempest/api/compute/images/test_images_oneserver_negative.py
+++ b/tempest/api/compute/images/test_images_oneserver_negative.py
@@ -22,7 +22,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -77,7 +76,7 @@
         server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('55d1d38c-dd66-4933-9c8e-7d92aeb60ddc')
     def test_create_image_specify_invalid_metadata(self):
         # Return an error when creating image with invalid metadata
@@ -85,7 +84,7 @@
         self.assertRaises(lib_exc.BadRequest, self.create_image_from_server,
                           self.server_id, metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3d24d11f-5366-4536-bd28-cff32b748eca')
     def test_create_image_specify_metadata_over_limits(self):
         # Return an error when creating image with meta data over 255 chars
@@ -93,7 +92,7 @@
         self.assertRaises(lib_exc.BadRequest, self.create_image_from_server,
                           self.server_id, metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0460efcf-ee88-4f94-acef-1bf658695456')
     def test_create_second_image_when_first_image_is_being_saved(self):
         # Disallow creating another image when first image is being saved
@@ -110,7 +109,7 @@
         self.client.delete_image(image_id)
         self.images.remove(image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('084f0cbc-500a-4963-8a4e-312905862581')
     def test_create_image_specify_name_over_character_limit(self):
         # Return an error if snapshot name over 255 characters is passed
@@ -119,7 +118,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.create_image,
                           self.server_id, name=snapshot_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0894954d-2db2-4195-a45b-ffec0bc0187e')
     def test_delete_image_that_is_not_yet_active(self):
         # Return an error while trying to delete an image what is creating
diff --git a/tempest/api/compute/images/test_list_image_filters_negative.py b/tempest/api/compute/images/test_list_image_filters_negative.py
index 403961f..d37f8fc 100644
--- a/tempest/api/compute/images/test_list_image_filters_negative.py
+++ b/tempest/api/compute/images/test_list_image_filters_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -36,7 +35,7 @@
         super(ListImageFiltersNegativeTestJSON, cls).setup_clients()
         cls.client = cls.compute_images_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('391b0440-432c-4d4b-b5da-c5096aa247eb')
     def test_get_nonexistent_image(self):
         # Check raises a NotFound
diff --git a/tempest/api/compute/keypairs/test_keypairs_negative.py b/tempest/api/compute/keypairs/test_keypairs_negative.py
index 8b5a35b..205076c 100644
--- a/tempest/api/compute/keypairs/test_keypairs_negative.py
+++ b/tempest/api/compute/keypairs/test_keypairs_negative.py
@@ -18,11 +18,10 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class KeyPairsNegativeTestJSON(base.BaseKeypairTest):
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('29cca892-46ae-4d48-bc32-8fe7e731eb81')
     def test_keypair_create_with_invalid_pub_key(self):
         # Keypair should not be created with a non RSA public key
@@ -30,7 +29,7 @@
         self.assertRaises(lib_exc.BadRequest,
                           self.create_keypair, pub_key=pub_key)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7cc32e47-4c42-489d-9623-c5e2cb5a2fa5')
     def test_keypair_delete_nonexistent_key(self):
         # Non-existent key deletion should throw a proper error
@@ -38,7 +37,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_keypair,
                           k_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('dade320e-69ca-42a9-ba4a-345300f127e0')
     def test_create_keypair_with_empty_public_key(self):
         # Keypair should not be created with an empty public key
@@ -46,7 +45,7 @@
         self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           pub_key=pub_key)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fc100c19-2926-4b9c-8fdc-d0589ee2f9ff')
     def test_create_keypair_when_public_key_bits_exceeds_maximum(self):
         # Keypair should not be created when public key bits are too long
@@ -54,7 +53,7 @@
         self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           pub_key=pub_key)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0359a7f1-f002-4682-8073-0c91e4011b7c')
     def test_create_keypair_with_duplicate_name(self):
         # Keypairs with duplicate names should not be created
@@ -65,14 +64,14 @@
                           k_name)
         self.client.delete_keypair(k_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1398abe1-4a84-45fb-9294-89f514daff00')
     def test_create_keypair_with_empty_name_string(self):
         # Keypairs with name being an empty string should not be created
         self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           '')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3faa916f-779f-4103-aca7-dc3538eee1b7')
     def test_create_keypair_with_long_keynames(self):
         # Keypairs with name longer than 255 chars should not be created
@@ -80,7 +79,7 @@
         self.assertRaises(lib_exc.BadRequest, self.create_keypair,
                           k_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('45fbe5e0-acb5-49aa-837a-ff8d0719db91')
     def test_create_keypair_invalid_name(self):
         # Keypairs with name being an invalid name should not be created
diff --git a/tempest/api/compute/limits/test_absolute_limits_negative.py b/tempest/api/compute/limits/test_absolute_limits_negative.py
index 21b4b1c..bef4eb5 100644
--- a/tempest/api/compute/limits/test_absolute_limits_negative.py
+++ b/tempest/api/compute/limits/test_absolute_limits_negative.py
@@ -17,7 +17,6 @@
 from tempest.common import tempest_fixtures as fixtures
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class AbsoluteLimitsNegativeTestJSON(base.BaseV2ComputeTest):
@@ -32,7 +31,7 @@
         super(AbsoluteLimitsNegativeTestJSON, cls).setup_clients()
         cls.client = cls.limits_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('215cd465-d8ae-49c9-bf33-9c911913a5c8')
     def test_max_image_meta_exceed_limit(self):
         # We should not create vm with image meta over maxImageMeta limit
diff --git a/tempest/api/compute/security_groups/test_security_group_rules.py b/tempest/api/compute/security_groups/test_security_group_rules.py
index a50933b..3378ef8 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules.py
@@ -53,7 +53,7 @@
             self.assertEqual(self.expected[key], actual_rule[key],
                              "Miss-matched key is %s" % key)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('850795d7-d4d3-4e55-b527-a774c0123d3a')
     @test.services('network')
     def test_security_group_rules_create(self):
@@ -123,7 +123,7 @@
                                   'name': group_name}
         self._check_expected_response(rule)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('a6154130-5a55-4850-8be4-5e9e796dbf17')
     @test.services('network')
     def test_security_group_rules_list(self):
diff --git a/tempest/api/compute/security_groups/test_security_group_rules_negative.py b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
index 6b8dfdf..4efb8b7 100644
--- a/tempest/api/compute/security_groups/test_security_group_rules_negative.py
+++ b/tempest/api/compute/security_groups/test_security_group_rules_negative.py
@@ -27,7 +27,7 @@
         super(SecurityGroupRulesNegativeTestJSON, cls).setup_clients()
         cls.rules_client = cls.security_group_rules_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1d507e98-7951-469b-82c3-23f1e6b8c254')
     @test.services('network')
     def test_create_security_group_rule_with_non_existent_id(self):
@@ -44,7 +44,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('2244d7e4-adb7-4ecb-9930-2d77e123ce4f')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_id(self):
@@ -61,7 +61,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8bd56d02-3ffa-4d67-9933-b6b9a01d6089')
     @test.services('network')
     def test_create_security_group_rule_duplicate(self):
@@ -86,7 +86,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('84c81249-9f6e-439c-9bbf-cbb0d2cddbdf')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_ip_protocol(self):
@@ -106,7 +106,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('12bbc875-1045-4f7a-be46-751277baedb9')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_from_port(self):
@@ -125,7 +125,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ff88804d-144f-45d1-bf59-dd155838a43a')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_to_port(self):
@@ -144,7 +144,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('00296fa9-0576-496a-ae15-fbab843189e0')
     @test.services('network')
     def test_create_security_group_rule_with_invalid_port_range(self):
@@ -163,7 +163,7 @@
                           ip_protocol=ip_protocol, from_port=from_port,
                           to_port=to_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('56fddcca-dbb8-4494-a0db-96e9f869527c')
     @test.services('network')
     def test_delete_security_group_rule_with_non_existent_id(self):
diff --git a/tempest/api/compute/security_groups/test_security_groups.py b/tempest/api/compute/security_groups/test_security_groups.py
index ed0e722..930a58e 100644
--- a/tempest/api/compute/security_groups/test_security_groups.py
+++ b/tempest/api/compute/security_groups/test_security_groups.py
@@ -28,7 +28,7 @@
         super(SecurityGroupsTestJSON, cls).setup_clients()
         cls.client = cls.security_groups_client
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('eb2b087d-633d-4d0d-a7bd-9e6ba35b32de')
     @test.services('network')
     def test_security_groups_create_list_delete(self):
diff --git a/tempest/api/compute/security_groups/test_security_groups_negative.py b/tempest/api/compute/security_groups/test_security_groups_negative.py
index 3593237..207778a 100644
--- a/tempest/api/compute/security_groups/test_security_groups_negative.py
+++ b/tempest/api/compute/security_groups/test_security_groups_negative.py
@@ -32,7 +32,7 @@
         super(SecurityGroupsNegativeTestJSON, cls).setup_clients()
         cls.client = cls.security_groups_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('673eaec1-9b3e-48ed-bdf1-2786c1b9661c')
     @test.services('network')
     def test_security_group_get_nonexistent_group(self):
@@ -44,7 +44,7 @@
 
     @decorators.skip_because(bug="1161411",
                              condition=CONF.service_available.neutron)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1759c3cb-b0fc-44b7-86ce-c99236be911d')
     @test.services('network')
     def test_security_group_create_with_invalid_group_name(self):
@@ -67,7 +67,7 @@
 
     @decorators.skip_because(bug="1161411",
                              condition=CONF.service_available.neutron)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('777b6f14-aca9-4758-9e84-38783cfa58bc')
     @test.services('network')
     def test_security_group_create_with_invalid_group_description(self):
@@ -84,7 +84,7 @@
     @decorators.idempotent_id('9fdb4abc-6b66-4b27-b89c-eb215a956168')
     @testtools.skipIf(CONF.service_available.neutron,
                       "Neutron allows duplicate names for security groups")
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @test.services('network')
     def test_security_group_create_with_duplicate_name(self):
         # Negative test:Security Group with duplicate name should not
@@ -97,7 +97,7 @@
                           self.client.create_security_group,
                           name=s_name, description=s_description)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('36a1629f-c6da-4a26-b8b8-55e7e5d5cd58')
     @test.services('network')
     def test_delete_the_default_security_group(self):
@@ -113,7 +113,7 @@
                           self.client.delete_security_group,
                           default_security_group_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6727c00b-214c-4f9e-9a52-017ac3e98411')
     @test.services('network')
     def test_delete_nonexistent_security_group(self):
@@ -122,7 +122,7 @@
         self.assertRaises(lib_exc.NotFound,
                           self.client.delete_security_group, non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1438f330-8fa4-4aeb-8a94-37c250106d7f')
     @test.services('network')
     def test_delete_security_group_without_passing_id(self):
@@ -134,7 +134,7 @@
     @decorators.idempotent_id('00579617-fe04-4e1c-9d08-ca7467d2e34b')
     @testtools.skipIf(CONF.service_available.neutron,
                       "Neutron does not check the security group ID")
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @test.services('network')
     def test_update_security_group_with_invalid_sg_id(self):
         # Update security_group with invalid sg_id should fail
@@ -149,7 +149,7 @@
     @decorators.idempotent_id('cda8d8b4-59f8-4087-821d-20cf5a03b3b1')
     @testtools.skipIf(CONF.service_available.neutron,
                       "Neutron does not check the security group name")
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @test.services('network')
     def test_update_security_group_with_invalid_sg_name(self):
         # Update security_group with invalid sg_name should fail
@@ -165,7 +165,7 @@
     @decorators.idempotent_id('97d12b1c-a610-4194-93f1-ba859e718b45')
     @testtools.skipIf(CONF.service_available.neutron,
                       "Neutron does not check the security group description")
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @test.services('network')
     def test_update_security_group_with_invalid_sg_des(self):
         # Update security_group with invalid sg_des should fail
@@ -178,7 +178,7 @@
                           self.client.update_security_group,
                           securitygroup_id, description=s_new_des)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('27edee9c-873d-4da6-a68a-3c256efebe8f')
     @test.services('network')
     def test_update_non_existent_security_group(self):
diff --git a/tempest/api/compute/servers/test_attach_interfaces.py b/tempest/api/compute/servers/test_attach_interfaces.py
index e0c8887..06a47d1 100644
--- a/tempest/api/compute/servers/test_attach_interfaces.py
+++ b/tempest/api/compute/servers/test_attach_interfaces.py
@@ -219,7 +219,7 @@
         _ifs = self._test_delete_interface(server, ifs)
         self.assertEqual(len(ifs) - 1, len(_ifs))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('c7e0e60b-ee45-43d0-abeb-8596fd42a2f9')
     @test.services('network')
     def test_add_remove_fixed_ip(self):
diff --git a/tempest/api/compute/servers/test_create_server.py b/tempest/api/compute/servers/test_create_server.py
index eb23e4b..d54c3ec 100644
--- a/tempest/api/compute/servers/test_create_server.py
+++ b/tempest/api/compute/servers/test_create_server.py
@@ -77,7 +77,7 @@
                         subnet['subnet']['id'])
         return net
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('5de47127-9977-400a-936f-abcfbec1218f')
     def test_verify_server_details(self):
         # Verify the specified server attributes are set correctly
@@ -91,7 +91,7 @@
         self.assertEqual(self.flavor_ref, self.server['flavor']['id'])
         self.assertEqual(self.meta, self.server['metadata'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('9a438d88-10c6-4bcd-8b5b-5b6e25e1346f')
     def test_list_servers(self):
         # The created server should be in the list of all servers
diff --git a/tempest/api/compute/servers/test_instance_actions_negative.py b/tempest/api/compute/servers/test_instance_actions_negative.py
index 512bd1e..1d3a790 100644
--- a/tempest/api/compute/servers/test_instance_actions_negative.py
+++ b/tempest/api/compute/servers/test_instance_actions_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class InstanceActionsNegativeTestJSON(base.BaseV2ComputeTest):
@@ -32,7 +31,7 @@
         super(InstanceActionsNegativeTestJSON, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('67e1fce6-7ec2-45c6-92d4-0a8f1a632910')
     def test_list_instance_actions_non_existent_server(self):
         # List actions of the non-existent server id
@@ -41,7 +40,7 @@
                           self.client.list_instance_actions,
                           non_existent_server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0269f40a-6f18-456c-b336-c03623c897f1')
     def test_get_instance_action_invalid_request(self):
         # Get the action details of the provided server with invalid request
diff --git a/tempest/api/compute/servers/test_list_servers_negative.py b/tempest/api/compute/servers/test_list_servers_negative.py
index 2e3d2bb..d89f44c 100644
--- a/tempest/api/compute/servers/test_list_servers_negative.py
+++ b/tempest/api/compute/servers/test_list_servers_negative.py
@@ -17,7 +17,6 @@
 from tempest.common import waiters
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ListServersNegativeTestJSON(base.BaseV2ComputeTest):
@@ -43,7 +42,7 @@
         waiters.wait_for_server_termination(cls.client, srv['id'])
         cls.deleted_fixtures.append(srv)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('24a26f1a-1ddc-4eea-b0d7-a90cc874ad8f')
     def test_list_servers_with_a_deleted_server(self):
         # Verify deleted servers do not show by default in list servers
@@ -55,7 +54,7 @@
                   if srv['id'] in deleted_ids]
         self.assertEqual([], actual)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ff01387d-c7ad-47b4-ae9e-64fa214638fe')
     def test_list_servers_by_non_existing_image(self):
         # Listing servers for a non existing image returns empty list
@@ -63,7 +62,7 @@
         servers = body['servers']
         self.assertEqual([], servers)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5913660b-223b-44d4-a651-a0fbfd44ca75')
     def test_list_servers_by_non_existing_flavor(self):
         # Listing servers by non existing flavor returns empty list
@@ -71,7 +70,7 @@
         servers = body['servers']
         self.assertEqual([], servers)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e2c77c4a-000a-4af3-a0bd-629a328bde7c')
     def test_list_servers_by_non_existing_server_name(self):
         # Listing servers for a non existent server name returns empty list
@@ -79,7 +78,7 @@
         servers = body['servers']
         self.assertEqual([], servers)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fcdf192d-0f74-4d89-911f-1ec002b822c4')
     def test_list_servers_status_non_existing(self):
         # Return an empty list when invalid status is specified
@@ -93,7 +92,7 @@
         body = self.client.list_servers(limit=1)
         self.assertEqual(1, len([x for x in body['servers'] if 'id' in x]))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d47c17fb-eebd-4287-8e95-f20a7e627b18')
     def test_list_servers_by_limits_greater_than_actual_count(self):
         # Gather the complete list of servers in the project for reference
@@ -103,21 +102,21 @@
         body = self.client.list_servers(limit=limit)
         self.assertEqual(len(full_list), len(body['servers']))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('679bc053-5e70-4514-9800-3dfab1a380a6')
     def test_list_servers_by_limits_pass_string(self):
         # Return an error if a string value is passed for limit
         self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
                           limit='testing')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('62610dd9-4713-4ee0-8beb-fd2c1aa7f950')
     def test_list_servers_by_limits_pass_negative_value(self):
         # Return an error if a negative value for limit is passed
         self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
                           limit=-1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('87d12517-e20a-4c9c-97b6-dd1628d6d6c9')
     def test_list_servers_by_changes_since_invalid_date(self):
         # Return an error when invalid date format is passed
@@ -125,7 +124,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.list_servers,
                           **params)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('74745ad8-b346-45b5-b9b8-509d7447fc1f')
     def test_list_servers_by_changes_since_future_date(self):
         # Return an empty list when a date in the future is passed
@@ -133,7 +132,7 @@
         body = self.client.list_servers(**changes_since)
         self.assertEqual(0, len(body['servers']))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('93055106-2d34-46fe-af68-d9ddbf7ee570')
     def test_list_servers_detail_server_is_deleted(self):
         # Server details are not listed for a deleted server
diff --git a/tempest/api/compute/servers/test_multiple_create_negative.py b/tempest/api/compute/servers/test_multiple_create_negative.py
index 675cbee..422510f 100644
--- a/tempest/api/compute/servers/test_multiple_create_negative.py
+++ b/tempest/api/compute/servers/test_multiple_create_negative.py
@@ -16,40 +16,39 @@
 from tempest.api.compute import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class MultipleCreateNegativeTestJSON(base.BaseV2ComputeTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('daf29d8d-e928-4a01-9a8c-b129603f3fc0')
     def test_min_count_less_than_one(self):
         invalid_min_count = 0
         self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           min_count=invalid_min_count)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('999aa722-d624-4423-b813-0d1ac9884d7a')
     def test_min_count_non_integer(self):
         invalid_min_count = 2.5
         self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           min_count=invalid_min_count)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a6f9c2ab-e060-4b82-b23c-4532cb9390ff')
     def test_max_count_less_than_one(self):
         invalid_max_count = 0
         self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           max_count=invalid_max_count)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9c5698d1-d7af-4c80-b971-9d403135eea2')
     def test_max_count_non_integer(self):
         invalid_max_count = 2.5
         self.assertRaises(lib_exc.BadRequest, self.create_test_server,
                           max_count=invalid_max_count)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('476da616-f1ef-4271-a9b1-b9fc87727cdf')
     def test_max_count_less_than_min_count(self):
         min_count = 3
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index d0f4b1b..751d33a 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -133,7 +133,7 @@
             self.assertGreater(new_boot_time, boot_time,
                                '%s > %s' % (new_boot_time, boot_time))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2cb1baf6-ac8d-4429-bf0d-ba8a0ba53e32')
     def test_reboot_server_hard(self):
         # The server should be power cycled
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index cf4ed85..92b1ff1 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -37,7 +37,7 @@
 
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('6eb718c0-02d9-4d5e-acd1-4e0c269cef39')
     @test.services('network')
     def test_list_server_addresses(self):
@@ -55,7 +55,7 @@
                 self.assertTrue(address['addr'])
                 self.assertTrue(address['version'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('87bbc374-5538-4f64-b673-2b0e4443cc30')
     @test.services('network')
     def test_list_server_addresses_by_network(self):
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index 1884e4f..76a102b 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -36,7 +36,7 @@
         super(ServerAddressesNegativeTestJSON, cls).resource_setup()
         cls.server = cls.create_test_server(wait_until='ACTIVE')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('02c3f645-2d2e-4417-8525-68c0407d001b')
     @test.services('network')
     def test_list_server_addresses_invalid_server_id(self):
@@ -44,7 +44,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.list_addresses,
                           '999')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a2ab5144-78c0-4942-a0ed-cc8edccfd9ba')
     @test.services('network')
     def test_list_server_addresses_by_network_neg(self):
diff --git a/tempest/api/compute/servers/test_server_metadata_negative.py b/tempest/api/compute/servers/test_server_metadata_negative.py
index 22ce37d..482ba09 100644
--- a/tempest/api/compute/servers/test_server_metadata_negative.py
+++ b/tempest/api/compute/servers/test_server_metadata_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ServerMetadataNegativeTestJSON(base.BaseV2ComputeTest):
@@ -33,7 +32,7 @@
         cls.tenant_id = cls.client.tenant_id
         cls.server = cls.create_test_server(metadata={}, wait_until='ACTIVE')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fe114a8f-3a57-4eff-9ee2-4e14628df049')
     def test_server_create_metadata_key_too_long(self):
         # Attempt to start a server with a meta-data key that is > 255
@@ -49,7 +48,7 @@
 
         # no teardown - all creates should fail
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('92431555-4d8b-467c-b95b-b17daa5e57ff')
     def test_create_server_metadata_blank_key(self):
         # Blank key should trigger an error.
@@ -58,7 +57,7 @@
                           self.create_test_server,
                           metadata=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4d9cd7a3-2010-4b41-b8fe-3bbf0b169466')
     def test_server_metadata_non_existent_server(self):
         # GET on a non-existent server should not succeed
@@ -68,7 +67,7 @@
                           non_existent_server_id,
                           'test2')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f408e78e-3066-4097-9299-3b0182da812e')
     def test_list_server_metadata_non_existent_server(self):
         # List metadata on a non-existent server should not succeed
@@ -77,7 +76,7 @@
                           self.client.list_server_metadata,
                           non_existent_server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0025fbd6-a4ba-4cde-b8c2-96805dcfdabc')
     def test_wrong_key_passed_in_body(self):
         # Raise BadRequest if key in uri does not match
@@ -87,7 +86,7 @@
                           self.client.set_server_metadata_item,
                           self.server['id'], 'key', meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0df38c2a-3d4e-4db5-98d8-d4d9fa843a12')
     def test_set_metadata_non_existent_server(self):
         # Set metadata on a non-existent server should not succeed
@@ -98,7 +97,7 @@
                           non_existent_server_id,
                           meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('904b13dc-0ef2-4e4c-91cd-3b4a0f2f49d8')
     def test_update_metadata_non_existent_server(self):
         # An update should not happen for a non-existent server
@@ -109,7 +108,7 @@
                           non_existent_server_id,
                           meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a452f38c-05c2-4b47-bd44-a4f0bf5a5e48')
     def test_update_metadata_with_blank_key(self):
         # Blank key should trigger an error
@@ -118,7 +117,7 @@
                           self.client.update_server_metadata,
                           self.server['id'], meta=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6bbd88e1-f8b3-424d-ba10-ae21c45ada8d')
     def test_delete_metadata_non_existent_server(self):
         # Should not be able to delete metadata item from a non-existent server
@@ -128,7 +127,7 @@
                           non_existent_server_id,
                           'd')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d8c0a210-a5c3-4664-be04-69d96746b547')
     def test_metadata_items_limit(self):
         # A 403 Forbidden or 413 Overlimit (old behaviour) exception
@@ -154,7 +153,7 @@
                           self.client.update_server_metadata,
                           self.server['id'], req_metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('96100343-7fa9-40d8-80fa-d29ef588ce1c')
     def test_set_server_metadata_blank_key(self):
         # Raise a bad request error for blank key.
@@ -164,7 +163,7 @@
                           self.client.set_server_metadata,
                           self.server['id'], meta=meta)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('64a91aee-9723-4863-be44-4c9d9f1e7d0e')
     def test_set_server_metadata_missing_metadata(self):
         # Raise a bad request error for a missing metadata field
diff --git a/tempest/api/compute/servers/test_server_rescue_negative.py b/tempest/api/compute/servers/test_server_rescue_negative.py
index 565d76d..5fac433 100644
--- a/tempest/api/compute/servers/test_server_rescue_negative.py
+++ b/tempest/api/compute/servers/test_server_rescue_negative.py
@@ -74,7 +74,7 @@
     @decorators.idempotent_id('cc3a883f-43c0-4fb6-a9bb-5579d64984ed')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_rescue_paused_instance(self):
         # Rescue a paused server
         self.servers_client.pause_server(self.server_id)
@@ -85,13 +85,13 @@
                           self.servers_client.rescue_server,
                           self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('db22b618-f157-4566-a317-1b6d467a8094')
     def test_rescued_vm_reboot(self):
         self.assertRaises(lib_exc.Conflict, self.servers_client.reboot_server,
                           self.rescue_id, type='HARD')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6dfc0a55-3a77-4564-a144-1587b7971dde')
     def test_rescue_non_existent_server(self):
         # Rescue a non-existing server
@@ -100,7 +100,7 @@
                           self.servers_client.rescue_server,
                           non_existent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('70cdb8a1-89f8-437d-9448-8844fd82bf46')
     def test_rescued_vm_rebuild(self):
         self.assertRaises(lib_exc.Conflict,
@@ -110,7 +110,7 @@
 
     @decorators.idempotent_id('d0ccac79-0091-4cf4-a1ce-26162d0cc55f')
     @test.services('volume')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_rescued_vm_attach_volume(self):
         volume = self.create_volume()
 
@@ -130,7 +130,7 @@
 
     @decorators.idempotent_id('f56e465b-fe10-48bf-b75d-646cda3a8bc9')
     @test.services('volume')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_rescued_vm_detach_volume(self):
         volume = self.create_volume()
 
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index 40a4289..2c6f96b 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -54,7 +54,7 @@
         server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('dbbfd247-c40c-449e-8f6c-d2aa7c7da7cf')
     def test_server_name_blank(self):
         # Create a server with name parameter empty
@@ -63,7 +63,7 @@
                           self.create_test_server,
                           name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b8a7235e-5246-4a8f-a08e-b34877c6586f')
     @testtools.skipUnless(CONF.compute_feature_enabled.personality,
                           'Nova personality feature disabled')
@@ -78,7 +78,7 @@
                           self.create_test_server,
                           personality=person)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fcba1052-0a50-4cf3-b1ac-fae241edf02f')
     def test_create_with_invalid_image(self):
         # Create a server with an unknown image
@@ -87,7 +87,7 @@
                           self.create_test_server,
                           image_id=-1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('18f5227f-d155-4429-807c-ccb103887537')
     def test_create_with_invalid_flavor(self):
         # Create a server with an unknown flavor
@@ -96,7 +96,7 @@
                           self.create_test_server,
                           flavor=-1,)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7f70a4d1-608f-4794-9e56-cb182765972c')
     def test_invalid_access_ip_v4_address(self):
         # An access IPv4 address must match a valid address pattern
@@ -105,7 +105,7 @@
         self.assertRaises(lib_exc.BadRequest,
                           self.create_test_server, accessIPv4=IPv4)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5226dd80-1e9c-4d8a-b5f9-b26ca4763fd0')
     def test_invalid_ip_v6_address(self):
         # An access IPv6 address must match a valid address pattern
@@ -118,7 +118,7 @@
     @decorators.idempotent_id('7ea45b3e-e770-46fa-bfcc-9daaf6d987c0')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_nonexistent_server(self):
         # Resize a non-existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -129,7 +129,7 @@
     @decorators.idempotent_id('ced1a1d7-2ab6-45c9-b90f-b27d87b30efd')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_server_with_non_existent_flavor(self):
         # Resize a server with non-existent flavor
         nonexistent_flavor = data_utils.rand_uuid()
@@ -139,13 +139,13 @@
     @decorators.idempotent_id('45436a7d-a388-4a35-a9d8-3adc5d0d940b')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resize_server_with_null_flavor(self):
         # Resize a server with null flavor
         self.assertRaises(lib_exc.BadRequest, self.client.resize_server,
                           self.server_id, flavor_ref="")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d4c023a0-9c55-4747-9dd5-413b820143c7')
     def test_reboot_non_existent_server(self):
         # Reboot a non existent server
@@ -156,7 +156,7 @@
     @decorators.idempotent_id('d1417e7f-a509-41b5-a102-d5eed8613369')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_pause_paused_server(self):
         # Pause a paused server.
         self.client.pause_server(self.server_id)
@@ -166,7 +166,7 @@
                           self.server_id)
         self.client.unpause_server(self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('98fa0458-1485-440f-873b-fe7f0d714930')
     def test_rebuild_deleted_server(self):
         # Rebuild a deleted server
@@ -179,7 +179,7 @@
                           server['id'], self.image_ref)
 
     @decorators.related_bug('1660878', status_code=409)
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('581a397d-5eab-486f-9cf9-1014bbd4c984')
     def test_reboot_deleted_server(self):
         # Reboot a deleted server
@@ -190,7 +190,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.reboot_server,
                           server['id'], type='SOFT')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d86141a7-906e-4731-b187-d64a2ea61422')
     def test_rebuild_non_existent_server(self):
         # Rebuild a non existent server
@@ -200,7 +200,7 @@
                           nonexistent_server,
                           self.image_ref)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('fd57f159-68d6-4c2a-902b-03070828a87e')
     def test_create_numeric_server_name(self):
         server_name = 12345
@@ -208,7 +208,7 @@
                           self.create_test_server,
                           name=server_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c3e0fb12-07fc-4d76-a22e-37409887afe8')
     def test_create_server_name_length_exceeds_256(self):
         # Create a server with name length exceeding 255 characters
@@ -218,7 +218,7 @@
                           self.create_test_server,
                           name=server_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.related_bug('1651064', status_code=500)
     @decorators.idempotent_id('12146ac1-d7df-4928-ad25-b1f99e5286cd')
     def test_create_server_invalid_bdm_in_2nd_dict(self):
@@ -238,7 +238,7 @@
                           image_id=self.image_ref,
                           block_device_mapping_v2=bdm)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4e72dc2d-44c5-4336-9667-f7972e95c402')
     def test_create_with_invalid_network_uuid(self):
         # Pass invalid network uuid while creating a server
@@ -249,7 +249,7 @@
                           self.create_test_server,
                           networks=networks)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7a2efc39-530c-47de-b875-2dd01c8d39bd')
     def test_create_with_non_existent_keypair(self):
         # Pass a non-existent keypair while creating a server
@@ -259,7 +259,7 @@
                           self.create_test_server,
                           key_name=key_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7fc74810-0bd2-4cd7-8244-4f33a9db865a')
     def test_create_server_metadata_exceeds_length_limit(self):
         # Pass really long metadata while creating a server
@@ -269,7 +269,7 @@
                           self.create_test_server,
                           metadata=metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('aa8eed43-e2cb-4ebf-930b-da14f6a21d81')
     def test_update_name_of_non_existent_server(self):
         # Update name of a non-existent server
@@ -281,7 +281,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.update_server,
                           nonexistent_server, name=new_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('38204696-17c6-44da-9590-40f87fb5a899')
     def test_update_server_set_empty_name(self):
         # Update name of the server to an empty string
@@ -291,7 +291,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.update_server,
                           self.server_id, name=new_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5c8e244c-dada-4590-9944-749c455b431f')
     def test_update_server_name_length_exceeds_256(self):
         # Update name of server exceed the name length limit
@@ -302,7 +302,7 @@
                           self.server_id,
                           name=new_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1041b4e6-514b-4855-96a5-e974b60870a3')
     def test_delete_non_existent_server(self):
         # Delete a non existent server
@@ -311,14 +311,14 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_server,
                           nonexistent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('75f79124-277c-45e6-a373-a1d6803f4cc4')
     def test_delete_server_pass_negative_id(self):
         # Pass an invalid string parameter to delete server
 
         self.assertRaises(lib_exc.NotFound, self.client.delete_server, -1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f4d7279b-5fd2-4bf2-9ba4-ae35df0d18c5')
     def test_delete_server_pass_id_exceeding_length_limit(self):
         # Pass a server ID that exceeds length limit to delete server
@@ -326,7 +326,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_server,
                           sys.maxsize + 1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c5fa6041-80cd-483b-aa6d-4e45f19d093c')
     def test_create_with_nonexistent_security_group(self):
         # Create a server with a nonexistent security group
@@ -336,7 +336,7 @@
                           self.create_test_server,
                           security_groups=security_groups)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3436b02f-1b1e-4f03-881e-c6a602327439')
     def test_get_non_existent_server(self):
         # Get a non existent server details
@@ -344,7 +344,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.show_server,
                           nonexistent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a31460a9-49e1-42aa-82ee-06e0bb7c2d03')
     def test_stop_non_existent_server(self):
         # Stop a non existent server
@@ -355,7 +355,7 @@
     @decorators.idempotent_id('6a8dc0c6-6cd4-4c0a-9f32-413881828091')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_pause_non_existent_server(self):
         # pause a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -365,7 +365,7 @@
     @decorators.idempotent_id('705b8e3a-e8a7-477c-a19b-6868fc24ac75')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_unpause_non_existent_server(self):
         # unpause a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -375,7 +375,7 @@
     @decorators.idempotent_id('c8e639a7-ece8-42dd-a2e0-49615917ba4f')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_unpause_server_invalid_state(self):
         # unpause an active server.
         self.assertRaises(lib_exc.Conflict,
@@ -385,7 +385,7 @@
     @decorators.idempotent_id('d1f032d5-7b6e-48aa-b252-d5f16dd994ca')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_suspend_non_existent_server(self):
         # suspend a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -395,7 +395,7 @@
     @decorators.idempotent_id('7f323206-05a9-4bf8-996b-dd5b2036501b')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_suspend_server_invalid_state(self):
         # suspend a suspended server.
         self.client.suspend_server(self.server_id)
@@ -409,7 +409,7 @@
     @decorators.idempotent_id('221cd282-bddb-4837-a683-89c2487389b6')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resume_non_existent_server(self):
         # resume a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -419,14 +419,14 @@
     @decorators.idempotent_id('ccb6294d-c4c9-498f-8a43-554c098bfadb')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_resume_server_invalid_state(self):
         # resume an active server.
         self.assertRaises(lib_exc.Conflict,
                           self.client.resume_server,
                           self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7dd919e7-413f-4198-bebb-35e2a01b13e9')
     def test_get_console_output_of_non_existent_server(self):
         # get the console output for a non existent server
@@ -435,7 +435,7 @@
                           self.client.get_console_output,
                           nonexistent_server, length=10)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6f47992b-5144-4250-9f8b-f00aa33950f3')
     def test_force_delete_nonexistent_server_id(self):
         # force-delete a non existent server
@@ -444,7 +444,7 @@
                           self.client.force_delete_server,
                           nonexistent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9c6d38cc-fcfb-437a-85b9-7b788af8bf01')
     def test_restore_nonexistent_server_id(self):
         # restore-delete a non existent server
@@ -453,7 +453,7 @@
                           self.client.restore_soft_deleted_server,
                           nonexistent_server)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7fcadfab-bd6a-4753-8db7-4a51e51aade9')
     def test_restore_server_invalid_state(self):
         # we can only restore-delete a server in 'soft-delete' state
@@ -464,7 +464,7 @@
     @decorators.idempotent_id('abca56e2-a892-48ea-b5e5-e07e69774816')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_shelve_non_existent_server(self):
         # shelve a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -474,7 +474,7 @@
     @decorators.idempotent_id('443e4f9b-e6bf-4389-b601-3a710f15fddd')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_shelve_shelved_server(self):
         # shelve a shelved server.
         compute.shelve_server(self.client, self.server_id)
@@ -495,7 +495,7 @@
     @decorators.idempotent_id('23d23b37-afaf-40d7-aa5d-5726f82d8821')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_unshelve_non_existent_server(self):
         # unshelve a non existent server
         nonexistent_server = data_utils.rand_uuid()
@@ -505,14 +505,14 @@
     @decorators.idempotent_id('8f198ded-1cca-4228-9e65-c6b449c54880')
     @testtools.skipUnless(CONF.compute_feature_enabled.shelve,
                           'Shelve is not available.')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_unshelve_server_invalid_state(self):
         # unshelve an active server.
         self.assertRaises(lib_exc.Conflict,
                           self.client.unshelve_server,
                           self.server_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('74085be3-a370-4ca2-bc51-2d0e10e0f573')
     @test.services('volume', 'image')
     def test_create_server_from_non_bootable_volume(self):
@@ -566,7 +566,7 @@
         server = cls.create_test_server(wait_until='ACTIVE')
         cls.server_id = server['id']
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('543d84c1-dd2e-4c6d-8cb2-b9da0efaa384')
     def test_update_server_of_another_tenant(self):
         # Update name of a server that belongs to another tenant
@@ -576,7 +576,7 @@
                           self.alt_client.update_server, self.server_id,
                           name=new_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5c75009d-3eea-423e-bea3-61b09fd25f9c')
     def test_delete_a_server_of_another_tenant(self):
         # Delete a server that belongs to another tenant
diff --git a/tempest/api/compute/servers/test_virtual_interfaces_negative.py b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
index b1374d2..173784a 100644
--- a/tempest/api/compute/servers/test_virtual_interfaces_negative.py
+++ b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
@@ -33,7 +33,7 @@
         super(VirtualInterfacesNegativeTestJSON, cls).setup_clients()
         cls.client = cls.servers_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('64ebd03c-1089-4306-93fa-60f5eb5c803c')
     @test.services('network')
     def test_list_virtual_interfaces_invalid_server_id(self):
diff --git a/tempest/api/compute/test_live_block_migration_negative.py b/tempest/api/compute/test_live_block_migration_negative.py
index 0f5ea57..ab63154 100644
--- a/tempest/api/compute/test_live_block_migration_negative.py
+++ b/tempest/api/compute/test_live_block_migration_negative.py
@@ -19,7 +19,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -37,7 +36,7 @@
             server_id, host=dest_host, block_migration=bmflm,
             disk_over_commit=False)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7fb7856e-ae92-44c9-861a-af62d7830bcb')
     def test_invalid_host_for_migration(self):
         # Migrating to an invalid host should not change the status
diff --git a/tempest/api/compute/test_versions.py b/tempest/api/compute/test_versions.py
index dcab067..6141553 100644
--- a/tempest/api/compute/test_versions.py
+++ b/tempest/api/compute/test_versions.py
@@ -14,13 +14,12 @@
 
 from tempest.api.compute import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class TestVersions(base.BaseV2ComputeTest):
 
     @decorators.idempotent_id('6c0a0990-43b6-4529-9b61-5fd8daf7c55c')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     def test_list_api_versions(self):
         """Test that a get of the unversioned url returns the choices doc.
 
@@ -39,7 +38,7 @@
                          "The first listed version should be v2.0")
 
     @decorators.idempotent_id('b953a29e-929c-4a8e-81be-ec3a7e03cb76')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     def test_get_version_details(self):
         """Test individual version endpoints info works.
 
diff --git a/tempest/api/compute/volumes/test_attach_volume_negative.py b/tempest/api/compute/volumes/test_attach_volume_negative.py
index c178a87..eabb907 100644
--- a/tempest/api/compute/volumes/test_attach_volume_negative.py
+++ b/tempest/api/compute/volumes/test_attach_volume_negative.py
@@ -16,7 +16,6 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -30,7 +29,7 @@
             skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
             raise cls.skipException(skip_msg)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.related_bug('1630783', status_code=500)
     @decorators.idempotent_id('a313b5cd-fbd0-49cc-94de-870e99f763c7')
     def test_delete_attached_volume(self):
diff --git a/tempest/api/compute/volumes/test_volumes_negative.py b/tempest/api/compute/volumes/test_volumes_negative.py
index 7676ee8..80db1be 100644
--- a/tempest/api/compute/volumes/test_volumes_negative.py
+++ b/tempest/api/compute/volumes/test_volumes_negative.py
@@ -18,7 +18,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -37,7 +36,7 @@
         super(VolumesNegativeTest, cls).setup_clients()
         cls.client = cls.volumes_extensions_client
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c03ea686-905b-41a2-8748-9635154b7c57')
     def test_volume_get_nonexistent_volume_id(self):
         # Negative: Should not be able to get details of nonexistent volume
@@ -46,7 +45,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.show_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('54a34226-d910-4b00-9ef8-8683e6c55846')
     def test_volume_delete_nonexistent_volume_id(self):
         # Negative: Should not be able to delete nonexistent Volume
@@ -55,7 +54,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5125ae14-152b-40a7-b3c5-eae15e9022ef')
     def test_create_volume_with_invalid_size(self):
         # Negative: Should not be able to create volume with invalid size
@@ -65,7 +64,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='#$%', display_name=v_name, metadata=metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('131cb3a1-75cc-4d40-b4c3-1317f64719b0')
     def test_create_volume_without_passing_size(self):
         # Negative: Should not be able to create volume without passing size
@@ -75,7 +74,7 @@
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='', display_name=v_name, metadata=metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8cce995e-0a83-479a-b94d-e1e40b8a09d1')
     def test_create_volume_with_size_zero(self):
         # Negative: Should not be able to create volume with size zero
@@ -84,13 +83,13 @@
         self.assertRaises(lib_exc.BadRequest, self.client.create_volume,
                           size='0', display_name=v_name, metadata=metadata)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('62bab09a-4c03-4617-8cca-8572bc94af9b')
     def test_get_volume_without_passing_volume_id(self):
         # Negative: Should not be able to get volume when empty ID is passed
         self.assertRaises(lib_exc.NotFound, self.client.show_volume, '')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('62972737-124b-4513-b6cf-2f019f178494')
     def test_delete_invalid_volume_id(self):
         # Negative: Should not be able to delete volume when invalid ID is
@@ -99,7 +98,7 @@
                           self.client.delete_volume,
                           data_utils.rand_name('invalid'))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0d1417c5-4ae8-4c2c-adc5-5f0b864253e5')
     def test_delete_volume_without_passing_volume_id(self):
         # Negative: Should not be able to delete volume when empty ID is passed
diff --git a/tempest/api/identity/admin/v2/test_roles_negative.py b/tempest/api/identity/admin/v2/test_roles_negative.py
index f80721c..86d06e2 100644
--- a/tempest/api/identity/admin/v2/test_roles_negative.py
+++ b/tempest/api/identity/admin/v2/test_roles_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class RolesNegativeTestJSON(base.BaseIdentityV2AdminTest):
@@ -28,14 +27,14 @@
         role = self.setup_test_role()
         return (user, tenant, role)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d5d5f1df-f8ca-4de0-b2ef-259c1cc67025')
     def test_list_roles_by_unauthorized_user(self):
         # Non-administrator user should not be able to list roles
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_roles_client.list_roles)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('11a3c7da-df6c-40c2-abc2-badd682edf9f')
     def test_list_roles_request_without_token(self):
         # Request to list roles without a valid token should fail
@@ -44,14 +43,14 @@
         self.assertRaises(lib_exc.Unauthorized, self.roles_client.list_roles)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c0b89e56-accc-4c73-85f8-9c0f866104c1')
     def test_role_create_blank_name(self):
         # Should not be able to create a role with a blank name
         self.assertRaises(lib_exc.BadRequest, self.roles_client.create_role,
                           name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('585c8998-a8a4-4641-a5dd-abef7a8ced00')
     def test_create_role_by_unauthorized_user(self):
         # Non-administrator user should not be able to create role
@@ -60,7 +59,7 @@
                           self.non_admin_roles_client.create_role,
                           name=role_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a7edd17a-e34a-4aab-8bb7-fa6f498645b8')
     def test_create_role_request_without_token(self):
         # Request to create role without a valid token should fail
@@ -71,7 +70,7 @@
                           self.roles_client.create_role, name=role_name)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c0cde2c8-81c1-4bb0-8fe2-cf615a3547a8')
     def test_role_create_duplicate(self):
         # Role names should be unique
@@ -82,7 +81,7 @@
         self.assertRaises(lib_exc.Conflict, self.roles_client.create_role,
                           name=role_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('15347635-b5b1-4a87-a280-deb2bd6d865e')
     def test_delete_role_by_unauthorized_user(self):
         # Non-administrator user should not be able to delete role
@@ -93,7 +92,7 @@
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_roles_client.delete_role, role_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('44b60b20-70de-4dac-beaf-a3fc2650a16b')
     def test_delete_role_request_without_token(self):
         # Request to delete role without a valid token should fail
@@ -108,7 +107,7 @@
                           role_id)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('38373691-8551-453a-b074-4260ad8298ef')
     def test_delete_role_non_existent(self):
         # Attempt to delete a non existent role should fail
@@ -116,7 +115,7 @@
         self.assertRaises(lib_exc.NotFound, self.roles_client.delete_role,
                           non_existent_role)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('391df5cf-3ec3-46c9-bbe5-5cb58dd4dc41')
     def test_assign_user_role_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to
@@ -127,7 +126,7 @@
             self.non_admin_roles_client.create_user_role_on_project,
             tenant['id'], user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f0d2683c-5603-4aee-95d7-21420e87cfd8')
     def test_assign_user_role_request_without_token(self):
         # Request to assign a role to a user without a valid token
@@ -140,7 +139,7 @@
             user['id'], role['id'])
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('99b297f6-2b5d-47c7-97a9-8b6bb4f91042')
     def test_assign_user_role_for_non_existent_role(self):
         # Attempt to assign a non existent role to user should fail
@@ -150,7 +149,7 @@
                           self.roles_client.create_user_role_on_project,
                           tenant['id'], user['id'], non_existent_role)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b2285aaa-9e76-4704-93a9-7a8acd0a6c8f')
     def test_assign_user_role_for_non_existent_tenant(self):
         # Attempt to assign a role on a non existent tenant should fail
@@ -160,7 +159,7 @@
                           self.roles_client.create_user_role_on_project,
                           non_existent_tenant, user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5c3132cd-c4c8-4402-b5ea-71eb44e97793')
     def test_assign_duplicate_user_role(self):
         # Duplicate user role should not get assigned
@@ -172,7 +171,7 @@
                           self.roles_client.create_user_role_on_project,
                           tenant['id'], user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d0537987-0977-448f-a435-904c15de7298')
     def test_remove_user_role_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to
@@ -186,7 +185,7 @@
             self.non_admin_roles_client.delete_role_from_user_on_project,
             tenant['id'], user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('cac81cf4-c1d2-47dc-90d3-f2b7eb572286')
     def test_remove_user_role_request_without_token(self):
         # Request to remove a user's role without a valid token
@@ -201,7 +200,7 @@
                           tenant['id'], user['id'], role['id'])
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ab32d759-cd16-41f1-a86e-44405fa9f6d2')
     def test_remove_user_role_non_existent_role(self):
         # Attempt to delete a non existent role from a user should fail
@@ -214,7 +213,7 @@
                           self.roles_client.delete_role_from_user_on_project,
                           tenant['id'], user['id'], non_existent_role)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('67a679ec-03dd-4551-bbfc-d1c93284f023')
     def test_remove_user_role_non_existent_tenant(self):
         # Attempt to remove a role from a non existent tenant should fail
@@ -227,7 +226,7 @@
                           self.roles_client.delete_role_from_user_on_project,
                           non_existent_tenant, user['id'], role['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7391ab4c-06f3-477a-a64a-c8e55ce89837')
     def test_list_user_roles_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to list
@@ -241,7 +240,7 @@
             self.non_admin_roles_client.list_user_roles_on_project,
             tenant['id'], user['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('682adfb2-fd5f-4b0a-a9ca-322e9bebb907')
     def test_list_user_roles_request_without_token(self):
         # Request to list user's roles without a valid token should fail
diff --git a/tempest/api/identity/admin/v2/test_services.py b/tempest/api/identity/admin/v2/test_services.py
index f6d4a24..634cf21 100644
--- a/tempest/api/identity/admin/v2/test_services.py
+++ b/tempest/api/identity/admin/v2/test_services.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ServicesTestJSON(base.BaseIdentityV2AdminTest):
@@ -78,7 +77,7 @@
         self.assertIn('type', service)
         self.assertEqual(s_type, service['type'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('34ea6489-012d-4a86-9038-1287cadd5eca')
     def test_list_services(self):
         # Create, List, Verify and Delete Services
diff --git a/tempest/api/identity/admin/v2/test_tenant_negative.py b/tempest/api/identity/admin/v2/test_tenant_negative.py
index 69f0920..750f9f9 100644
--- a/tempest/api/identity/admin/v2/test_tenant_negative.py
+++ b/tempest/api/identity/admin/v2/test_tenant_negative.py
@@ -17,19 +17,18 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class TenantsNegativeTestJSON(base.BaseIdentityV2AdminTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ca9bb202-63dd-4240-8a07-8ef9c19c04bb')
     def test_list_tenants_by_unauthorized_user(self):
         # Non-administrator user should not be able to list tenants
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_tenants_client.list_tenants)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('df33926c-1c96-4d8d-a762-79cc6b0c3cf4')
     def test_list_tenant_request_without_token(self):
         # Request to list tenants without a valid token should fail
@@ -39,7 +38,7 @@
                           self.tenants_client.list_tenants)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('162ba316-f18b-4987-8c0c-fd9140cd63ed')
     def test_tenant_delete_by_unauthorized_user(self):
         # Non-administrator user should not be able to delete a tenant
@@ -50,7 +49,7 @@
                           self.non_admin_tenants_client.delete_tenant,
                           tenant['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e450db62-2e9d-418f-893a-54772d6386b1')
     def test_tenant_delete_request_without_token(self):
         # Request to delete a tenant without a valid token should fail
@@ -64,14 +63,14 @@
                           tenant['id'])
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9c9a2aed-6e3c-467a-8f5c-89da9d1b516b')
     def test_delete_non_existent_tenant(self):
         # Attempt to delete a non existent tenant should fail
         self.assertRaises(lib_exc.NotFound, self.tenants_client.delete_tenant,
                           data_utils.rand_uuid_hex())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('af16f44b-a849-46cb-9f13-a751c388f739')
     def test_tenant_create_duplicate(self):
         # Tenant names should be unique
@@ -83,7 +82,7 @@
         self.assertRaises(lib_exc.Conflict, self.tenants_client.create_tenant,
                           name=tenant_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d26b278a-6389-4702-8d6e-5980d80137e0')
     def test_create_tenant_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to create a tenant
@@ -92,7 +91,7 @@
                           self.non_admin_tenants_client.create_tenant,
                           name=tenant_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a3ee9d7e-6920-4dd5-9321-d4b2b7f0a638')
     def test_create_tenant_request_without_token(self):
         # Create tenant request without a token should not be authorized
@@ -104,7 +103,7 @@
                           name=tenant_name)
         self.client.auth_provider.clear_auth()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5a2e4ca9-b0c0-486c-9c48-64a94fba2395')
     def test_create_tenant_with_empty_name(self):
         # Tenant name should not be empty
@@ -112,7 +111,7 @@
                           self.tenants_client.create_tenant,
                           name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('2ff18d1e-dfe3-4359-9dc3-abf582c196b9')
     def test_create_tenants_name_length_over_64(self):
         # Tenant name length should not be greater than 64 characters
@@ -121,14 +120,14 @@
                           self.tenants_client.create_tenant,
                           name=tenant_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bd20dc2a-9557-4db7-b755-f48d952ad706')
     def test_update_non_existent_tenant(self):
         # Attempt to update a non existent tenant should fail
         self.assertRaises(lib_exc.NotFound, self.tenants_client.update_tenant,
                           data_utils.rand_uuid_hex())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('41704dc5-c5f7-4f79-abfa-76e6fedc570b')
     def test_tenant_update_by_unauthorized_user(self):
         # Non-administrator user should not be able to update a tenant
@@ -139,7 +138,7 @@
                           self.non_admin_tenants_client.update_tenant,
                           tenant['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7a421573-72c7-4c22-a98e-ce539219c657')
     def test_tenant_update_request_without_token(self):
         # Request to update a tenant without a valid token should fail
diff --git a/tempest/api/identity/admin/v2/test_users.py b/tempest/api/identity/admin/v2/test_users.py
index af94b54..2711a2d 100644
--- a/tempest/api/identity/admin/v2/test_users.py
+++ b/tempest/api/identity/admin/v2/test_users.py
@@ -20,7 +20,6 @@
 from tempest.api.identity import base
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class UsersTestJSON(base.BaseIdentityV2AdminTest):
@@ -31,7 +30,7 @@
         cls.alt_user = data_utils.rand_name('test_user')
         cls.alt_email = cls.alt_user + '@testmail.tm'
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2d55a71e-da1d-4b43-9c03-d269fd93d905')
     def test_create_user(self):
         # Create a user
diff --git a/tempest/api/identity/admin/v2/test_users_negative.py b/tempest/api/identity/admin/v2/test_users_negative.py
index 442c1a7..4f47e41 100644
--- a/tempest/api/identity/admin/v2/test_users_negative.py
+++ b/tempest/api/identity/admin/v2/test_users_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class UsersNegativeTestJSON(base.BaseIdentityV2AdminTest):
@@ -29,7 +28,7 @@
         cls.alt_password = data_utils.rand_password()
         cls.alt_email = cls.alt_user + '@testmail.tm'
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('60a1f5fa-5744-4cdf-82bf-60b7de2d29a4')
     def test_create_user_by_unauthorized_user(self):
         # Non-administrator should not be authorized to create a user
@@ -40,7 +39,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d80d0c2f-4514-4d1e-806d-0930dfc5a187')
     def test_create_user_with_empty_name(self):
         # User with an empty name should not be created
@@ -50,7 +49,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7704b4f3-3b75-4b82-87cc-931d41c8f780')
     def test_create_user_with_name_length_over_255(self):
         # Length of user name filed should be restricted to 255 characters
@@ -60,7 +59,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('57ae8558-120c-4723-9308-3751474e7ecf')
     def test_create_user_with_duplicate_name(self):
         # Duplicate user should not be created
@@ -73,7 +72,7 @@
                           tenantId=tenant['id'],
                           email=user['email'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0132cc22-7c4f-42e1-9e50-ac6aad31d59a')
     def test_create_user_for_non_existent_tenant(self):
         # Attempt to create a user in a non-existent tenant should fail
@@ -83,7 +82,7 @@
                           tenantId='49ffgg99999',
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('55bbb103-d1ae-437b-989b-bcdf8175c1f4')
     def test_create_user_request_without_a_token(self):
         # Request to create a user without a valid token should fail
@@ -101,7 +100,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('23a2f3da-4a1a-41da-abdd-632328a861ad')
     def test_create_user_with_enabled_non_bool(self):
         # Attempt to create a user with valid enabled para should fail
@@ -112,7 +111,7 @@
                           tenantId=tenant['id'],
                           email=self.alt_email, enabled=3)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3d07e294-27a0-4144-b780-a2a1bf6fee19')
     def test_update_user_for_non_existent_user(self):
         # Attempt to update a user non-existent user should fail
@@ -121,7 +120,7 @@
         self.assertRaises(lib_exc.NotFound, self.users_client.update_user,
                           non_existent_id, name=user_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('3cc2a64b-83aa-4b02-88f0-d6ab737c4466')
     def test_update_user_request_without_a_token(self):
         # Request to update a user without a valid token should fail
@@ -137,7 +136,7 @@
         self.assertRaises(lib_exc.Unauthorized, self.users_client.update_user,
                           self.alt_user)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('424868d5-18a7-43e1-8903-a64f95ee3aac')
     def test_update_user_by_unauthorized_user(self):
         # Non-administrator should not be authorized to update user
@@ -145,7 +144,7 @@
                           self.non_admin_users_client.update_user,
                           self.alt_user)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d45195d5-33ed-41b9-a452-7d0d6a00f6e9')
     def test_delete_users_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to delete a user
@@ -154,14 +153,14 @@
                           self.non_admin_users_client.delete_user,
                           user['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7cc82f7e-9998-4f89-abae-23df36495867')
     def test_delete_non_existent_user(self):
         # Attempt to delete a non-existent user should fail
         self.assertRaises(lib_exc.NotFound, self.users_client.delete_user,
                           'junk12345123')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('57fe1df8-0aa7-46c0-ae9f-c2e785c7504a')
     def test_delete_user_request_without_a_token(self):
         # Request to delete a user without a valid token should fail
@@ -177,7 +176,7 @@
         self.assertRaises(lib_exc.Unauthorized, self.users_client.delete_user,
                           self.alt_user)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('593a4981-f6d4-460a-99a1-57a78bf20829')
     def test_authentication_for_disabled_user(self):
         # Disabled user's token should not get authenticated
@@ -190,7 +189,7 @@
                           password,
                           tenant['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('440a7a8d-9328-4b7b-83e0-d717010495e4')
     def test_authentication_when_tenant_is_disabled(self):
         # User's token for a disabled tenant should not be authenticated
@@ -203,7 +202,7 @@
                           password,
                           tenant['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('921f1ad6-7907-40b8-853f-637e7ee52178')
     def test_authentication_with_invalid_tenant(self):
         # User's token for an invalid tenant should not be authenticated
@@ -214,7 +213,7 @@
                           password,
                           'junktenant1234')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bde9aecd-3b1c-4079-858f-beb5deaa5b5e')
     def test_authentication_with_invalid_username(self):
         # Non-existent user's token should not get authenticated
@@ -224,7 +223,7 @@
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
                           'junkuser123', password, tenant['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d5308b33-3574-43c3-8d87-1c090c5e1eca')
     def test_authentication_with_invalid_password(self):
         # User's token with invalid password should not be authenticated
@@ -233,14 +232,14 @@
         self.assertRaises(lib_exc.Unauthorized, self.token_client.auth,
                           user['name'], 'junkpass1234', tenant['name'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('284192ce-fb7c-4909-a63b-9a502e0ddd11')
     def test_get_users_by_unauthorized_user(self):
         # Non-administrator user should not be authorized to get user list
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_users_client.list_users)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a73591ec-1903-4ffe-be42-282b39fefc9d')
     def test_get_users_request_without_token(self):
         # Request to get list of users without a valid token should fail
@@ -252,7 +251,7 @@
 
         self.assertRaises(lib_exc.Unauthorized, self.users_client.list_users)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f5d39046-fc5f-425c-b29e-bac2632da28e')
     def test_list_users_with_invalid_tenant(self):
         # Should not be able to return a list of all
diff --git a/tempest/api/identity/admin/v3/test_credentials.py b/tempest/api/identity/admin/v3/test_credentials.py
index c752532..75e877a 100644
--- a/tempest/api/identity/admin/v3/test_credentials.py
+++ b/tempest/api/identity/admin/v3/test_credentials.py
@@ -17,7 +17,6 @@
 from tempest.api.identity import base
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class CredentialsTestJSON(base.BaseIdentityV3AdminTest):
@@ -52,7 +51,7 @@
     def _delete_credential(self, cred_id):
         self.creds_client.delete_credential(cred_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('7cd59bf9-bda4-4c72-9467-d21cab278355')
     def test_credentials_create_get_update_delete(self):
         blob = '{"access": "%s", "secret": "%s"}' % (
diff --git a/tempest/api/identity/admin/v3/test_domains.py b/tempest/api/identity/admin/v3/test_domains.py
index d04e774..86a5764 100644
--- a/tempest/api/identity/admin/v3/test_domains.py
+++ b/tempest/api/identity/admin/v3/test_domains.py
@@ -18,7 +18,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 
@@ -87,7 +86,7 @@
         for domain in fetched_domains:
             self.assertEqual(True, domain['enabled'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f2f5b44a-82e8-4dad-8084-0661ea3b18cf')
     def test_create_update_delete_domain(self):
         # Create domain
@@ -168,7 +167,7 @@
         cls.domain_id = CONF.identity.default_domain_id
         super(DefaultDomainTestJSON, cls).resource_setup()
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('17a5de24-e6a0-4e4a-a9ee-d85b6e5612b5')
     def test_default_domain_exists(self):
         domain = self.domains_client.show_domain(self.domain_id)['domain']
diff --git a/tempest/api/identity/admin/v3/test_domains_negative.py b/tempest/api/identity/admin/v3/test_domains_negative.py
index 280a5a8..61b4fa2 100644
--- a/tempest/api/identity/admin/v3/test_domains_negative.py
+++ b/tempest/api/identity/admin/v3/test_domains_negative.py
@@ -17,13 +17,12 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class DomainsNegativeTestJSON(base.BaseIdentityV3AdminTest):
     _interface = 'json'
 
-    @test.attr(type=['negative', 'gate'])
+    @decorators.attr(type=['negative', 'gate'])
     @decorators.idempotent_id('1f3fbff5-4e44-400d-9ca1-d953f05f609b')
     def test_delete_active_domain(self):
         d_name = data_utils.rand_name('domain')
@@ -39,14 +38,14 @@
         self.assertRaises(lib_exc.Forbidden, self.domains_client.delete_domain,
                           domain_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9018461d-7d24-408d-b3fe-ae37e8cd5c9e')
     def test_create_domain_with_empty_name(self):
         # Domain name should not be empty
         self.assertRaises(lib_exc.BadRequest,
                           self.domains_client.create_domain, name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('37b1bbf2-d664-4785-9a11-333438586eae')
     def test_create_domain_with_name_length_over_64(self):
         # Domain name length should not ne greater than 64 characters
@@ -55,14 +54,14 @@
                           self.domains_client.create_domain,
                           name=d_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('43781c07-764f-4cf2-a405-953c1916f605')
     def test_delete_non_existent_domain(self):
         # Attempt to delete a non existent domain should fail
         self.assertRaises(lib_exc.NotFound, self.domains_client.delete_domain,
                           data_utils.rand_uuid_hex())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e6f9e4a2-4f36-4be8-bdbc-4e199ae29427')
     def test_domain_create_duplicate(self):
         domain_name = data_utils.rand_name('domain-dup')
diff --git a/tempest/api/identity/admin/v3/test_endpoints.py b/tempest/api/identity/admin/v3/test_endpoints.py
index 0786d82..09f92e2 100644
--- a/tempest/api/identity/admin/v3/test_endpoints.py
+++ b/tempest/api/identity/admin/v3/test_endpoints.py
@@ -16,7 +16,6 @@
 from tempest.api.identity import base
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class EndPointsTestJSON(base.BaseIdentityV3AdminTest):
@@ -109,7 +108,7 @@
         fetched_endpoints_id = [e['id'] for e in fetched_endpoints]
         self.assertNotIn(endpoint['id'], fetched_endpoints_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('37e8f15e-ee7c-4657-a1e7-f6b61e375eff')
     def test_update_endpoint(self):
         # Creating an endpoint so as to check update endpoint
diff --git a/tempest/api/identity/admin/v3/test_endpoints_negative.py b/tempest/api/identity/admin/v3/test_endpoints_negative.py
index d46e1f0..70dd7b5 100644
--- a/tempest/api/identity/admin/v3/test_endpoints_negative.py
+++ b/tempest/api/identity/admin/v3/test_endpoints_negative.py
@@ -18,7 +18,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class EndpointsNegativeTestJSON(base.BaseIdentityV3AdminTest):
@@ -48,7 +47,7 @@
             cls.services_client.delete_service(s)
         super(EndpointsNegativeTestJSON, cls).resource_cleanup()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ac6c137e-4d3d-448f-8c83-4f13d0942651')
     def test_create_with_enabled_False(self):
         # Enabled should be a boolean, not a string like 'False'
@@ -59,7 +58,7 @@
                           service_id=self.service_id, interface=interface,
                           url=url, region=region, enabled='False')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9c43181e-0627-484a-8c79-923e8a59598b')
     def test_create_with_enabled_True(self):
         # Enabled should be a boolean, not a string like 'True'
@@ -86,13 +85,13 @@
         self.assertRaises(lib_exc.BadRequest, self.client.update_endpoint,
                           endpoint_for_update['id'], enabled=enabled)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('65e41f32-5eb7-498f-a92a-a6ccacf7439a')
     def test_update_with_enabled_False(self):
         # Enabled should be a boolean, not a string like 'False'
         self._assert_update_raises_bad_request('False')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('faba3587-f066-4757-a48e-b4a3f01803bb')
     def test_update_with_enabled_True(self):
         # Enabled should be a boolean, not a string like 'True'
diff --git a/tempest/api/identity/admin/v3/test_groups.py b/tempest/api/identity/admin/v3/test_groups.py
index 8fdd0ec..2694402 100644
--- a/tempest/api/identity/admin/v3/test_groups.py
+++ b/tempest/api/identity/admin/v3/test_groups.py
@@ -16,7 +16,6 @@
 from tempest.api.identity import base
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class GroupsV3TestJSON(base.BaseIdentityV3AdminTest):
@@ -72,7 +71,7 @@
         # Verify that 'description' is not being updated or deleted.
         self.assertEqual(old_description, updated_group['description'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('1598521a-2f36-4606-8df9-30772bd51339')
     def test_group_users_add_list_delete(self):
         name = data_utils.rand_name('Group')
diff --git a/tempest/api/identity/admin/v3/test_policies.py b/tempest/api/identity/admin/v3/test_policies.py
index f74cb1c..730d469 100644
--- a/tempest/api/identity/admin/v3/test_policies.py
+++ b/tempest/api/identity/admin/v3/test_policies.py
@@ -16,7 +16,6 @@
 from tempest.api.identity import base
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class PoliciesTestJSON(base.BaseIdentityV3AdminTest):
@@ -44,7 +43,7 @@
         missing_pols = [p for p in policy_ids if p not in fetched_ids]
         self.assertEqual(0, len(missing_pols))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('e544703a-2f03-4cf2-9b0f-350782fdb0d3')
     def test_create_update_delete_policy(self):
         # Test to update policy
diff --git a/tempest/api/identity/admin/v3/test_projects_negative.py b/tempest/api/identity/admin/v3/test_projects_negative.py
index 31e7302..6277fda 100644
--- a/tempest/api/identity/admin/v3/test_projects_negative.py
+++ b/tempest/api/identity/admin/v3/test_projects_negative.py
@@ -17,19 +17,18 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ProjectsNegativeTestJSON(base.BaseIdentityV3AdminTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('24c49279-45dd-4155-887a-cb738c2385aa')
     def test_list_projects_by_unauthorized_user(self):
         # Non-admin user should not be able to list projects
         self.assertRaises(lib_exc.Forbidden,
                           self.non_admin_projects_client.list_projects)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('874c3e84-d174-4348-a16b-8c01f599561b')
     def test_project_create_duplicate(self):
         # Project names should be unique
@@ -40,7 +39,7 @@
         self.assertRaises(lib_exc.Conflict,
                           self.projects_client.create_project, project_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8fba9de2-3e1f-4e77-812a-60cb68f8df13')
     def test_create_project_by_unauthorized_user(self):
         # Non-admin user should not be authorized to create a project
@@ -49,14 +48,14 @@
             lib_exc.Forbidden, self.non_admin_projects_client.create_project,
             project_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7828db17-95e5-475b-9432-9a51b4aa79a9')
     def test_create_project_with_empty_name(self):
         # Project name should not be empty
         self.assertRaises(lib_exc.BadRequest,
                           self.projects_client.create_project, name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('502b6ceb-b0c8-4422-bf53-f08fdb21e2f0')
     def test_create_projects_name_length_over_64(self):
         # Project name length should not be greater than 64 characters
@@ -64,7 +63,7 @@
         self.assertRaises(lib_exc.BadRequest,
                           self.projects_client.create_project, project_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8d68c012-89e0-4394-8d6b-ccd7196def97')
     def test_project_delete_by_unauthorized_user(self):
         # Non-admin user should not be able to delete a project
@@ -75,7 +74,7 @@
             lib_exc.Forbidden, self.non_admin_projects_client.delete_project,
             project['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7965b581-60c1-43b7-8169-95d4ab7fc6fb')
     def test_delete_non_existent_project(self):
         # Attempt to delete a non existent project should fail
diff --git a/tempest/api/identity/admin/v3/test_regions.py b/tempest/api/identity/admin/v3/test_regions.py
index 56ee496..ac550a7 100644
--- a/tempest/api/identity/admin/v3/test_regions.py
+++ b/tempest/api/identity/admin/v3/test_regions.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class RegionsTestJSON(base.BaseIdentityV3AdminTest):
@@ -79,7 +78,7 @@
         regions_list = [r['id'] for r in body]
         self.assertNotIn(region['id'], regions_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2c12c5b5-efcf-4aa5-90c5-bff1ab0cdbe2')
     def test_create_region_with_specific_id(self):
         # Create a region with a specific id
diff --git a/tempest/api/identity/admin/v3/test_roles.py b/tempest/api/identity/admin/v3/test_roles.py
index 04be00b..ac56fc6 100644
--- a/tempest/api/identity/admin/v3/test_roles.py
+++ b/tempest/api/identity/admin/v3/test_roles.py
@@ -19,7 +19,6 @@
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -74,7 +73,7 @@
         self.assertEqual(len(body), 1)
         self.assertIn(role_id, fetched_role_ids)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('18afc6c0-46cf-4911-824e-9989cc056c3a')
     def test_role_create_update_show_list(self):
         r_name = data_utils.rand_name('Role')
diff --git a/tempest/api/identity/admin/v3/test_services.py b/tempest/api/identity/admin/v3/test_services.py
index 53e005d..ad4e549 100644
--- a/tempest/api/identity/admin/v3/test_services.py
+++ b/tempest/api/identity/admin/v3/test_services.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ServicesTestJSON(base.BaseIdentityV3AdminTest):
@@ -29,7 +28,7 @@
         self.assertRaises(lib_exc.NotFound, self.services_client.show_service,
                           service_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('5193aad5-bcb7-411d-85b0-b3b61b96ef06')
     def test_create_update_get_service(self):
         # Creating a Service
diff --git a/tempest/api/identity/admin/v3/test_trusts.py b/tempest/api/identity/admin/v3/test_trusts.py
index ec64e0c..339b4bb 100644
--- a/tempest/api/identity/admin/v3/test_trusts.py
+++ b/tempest/api/identity/admin/v3/test_trusts.py
@@ -22,7 +22,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -265,7 +264,7 @@
         self.assertEqual(1, len(trusts_get))
         self.validate_trust(trusts_get[0], summary=True)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('4773ebd5-ecbf-4255-b8d8-b63e6f72b65d')
     def test_get_trusts_all(self):
 
diff --git a/tempest/api/identity/admin/v3/test_users_negative.py b/tempest/api/identity/admin/v3/test_users_negative.py
index 93241c5..09d1b9b 100644
--- a/tempest/api/identity/admin/v3/test_users_negative.py
+++ b/tempest/api/identity/admin/v3/test_users_negative.py
@@ -17,12 +17,11 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class UsersNegativeTest(base.BaseIdentityV3AdminTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e75f006c-89cc-477b-874d-588e4eab4b17')
     def test_create_user_for_non_existent_domain(self):
         # Attempt to create a user in a non-existent domain should fail
@@ -34,7 +33,7 @@
                           email=u_email,
                           domain_id=data_utils.rand_uuid_hex())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b3c9fccc-4134-46f5-b600-1da6fb0a3b1f')
     def test_authentication_for_disabled_user(self):
         # Attempt to authenticate for disabled user should fail
diff --git a/tempest/api/identity/v2/test_api_discovery.py b/tempest/api/identity/v2/test_api_discovery.py
index 02caef5..5b9d38c 100644
--- a/tempest/api/identity/v2/test_api_discovery.py
+++ b/tempest/api/identity/v2/test_api_discovery.py
@@ -15,13 +15,12 @@
 
 from tempest.api.identity import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class TestApiDiscovery(base.BaseIdentityV2Test):
     """Tests for API discovery features."""
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('ea889a68-a15f-4166-bfb1-c12456eae853')
     def test_api_version_resources(self):
         descr = self.non_admin_client.show_api_description()['version']
@@ -32,7 +31,7 @@
         for res in expected_resources:
             self.assertIn(res, keys)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('007a0be0-78fe-4fdb-bbee-e9216cc17bb2')
     def test_api_media_types(self):
         descr = self.non_admin_client.show_api_description()['version']
@@ -47,7 +46,7 @@
         for s_type in supported_types:
             self.assertIn(s_type, media_types)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('77fd6be0-8801-48e6-b9bf-38cdd2f253ec')
     def test_api_version_statuses(self):
         descr = self.non_admin_client.show_api_description()['version']
diff --git a/tempest/api/identity/v3/test_api_discovery.py b/tempest/api/identity/v3/test_api_discovery.py
index 177a49d..c04c21b 100644
--- a/tempest/api/identity/v3/test_api_discovery.py
+++ b/tempest/api/identity/v3/test_api_discovery.py
@@ -15,14 +15,13 @@
 
 from tempest.api.identity import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class TestApiDiscovery(base.BaseIdentityV3Test):
     """Tests for API discovery features."""
 
     @decorators.idempotent_id('721f480f-35b6-46c7-846e-047e6acea0dc')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     def test_list_api_versions(self):
         # NOTE: Actually this API doesn't depend on v3 API at all, because
         # the API operation is "GET /" without v3's endpoint. The reason of
@@ -35,7 +34,7 @@
             for res in expected_resources:
                 self.assertIn(res, version)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('b9232f5e-d9e5-4d97-b96c-28d3db4de1bd')
     def test_api_version_resources(self):
         descr = self.non_admin_client.show_api_description()['version']
@@ -46,7 +45,7 @@
         for res in expected_resources:
             self.assertIn(res, keys)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('657c1970-4722-4189-8831-7325f3bc4265')
     def test_api_media_types(self):
         descr = self.non_admin_client.show_api_description()['version']
@@ -61,7 +60,7 @@
         for s_type in supported_types:
             self.assertIn(s_type, media_types)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('8879a470-abfb-47bb-bb8d-5a7fd279ad1e')
     def test_api_version_statuses(self):
         descr = self.non_admin_client.show_api_description()['version']
diff --git a/tempest/api/image/v1/test_image_members_negative.py b/tempest/api/image/v1/test_image_members_negative.py
index f075cab..2748bd5 100644
--- a/tempest/api/image/v1/test_image_members_negative.py
+++ b/tempest/api/image/v1/test_image_members_negative.py
@@ -16,12 +16,11 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ImageMembersNegativeTest(base.BaseV1ImageMembersTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('147a9536-18e3-45da-91ea-b037a028f364')
     def test_add_member_with_non_existing_image(self):
         # Add member with non existing image.
@@ -30,7 +29,7 @@
                           self.image_member_client.create_image_member,
                           non_exist_image, self.alt_tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e1559f05-b667-4f1b-a7af-518b52dc0c0f')
     def test_delete_member_with_non_existing_image(self):
         # Delete member with non existing image.
@@ -39,7 +38,7 @@
                           self.image_member_client.delete_image_member,
                           non_exist_image, self.alt_tenant_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f5720333-dd69-4194-bb76-d2f048addd56')
     def test_delete_member_with_non_existing_tenant(self):
         # Delete member with non existing tenant.
@@ -49,7 +48,7 @@
                           self.image_member_client.delete_image_member,
                           image_id, non_exist_tenant)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f25f89e4-0b6c-453b-a853-1f80b9d7ef26')
     def test_get_image_without_membership(self):
         # Image is hidden from another tenants.
diff --git a/tempest/api/image/v1/test_images_negative.py b/tempest/api/image/v1/test_images_negative.py
index 42ff02f..690b8da 100644
--- a/tempest/api/image/v1/test_images_negative.py
+++ b/tempest/api/image/v1/test_images_negative.py
@@ -18,13 +18,12 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class CreateDeleteImagesNegativeTest(base.BaseV1ImageTest):
     """Here are negative tests for the deletion and creation of images."""
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('036ede36-6160-4463-8c01-c781eee6369d')
     def test_register_with_invalid_container_format(self):
         # Negative tests for invalid data supplied to POST /images
@@ -33,7 +32,7 @@
                                    'x-image-meta-container_format': 'wrong',
                                    'x-image-meta-disk_format': 'vhd'})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('993face5-921d-4e84-aabf-c1bba4234a67')
     def test_register_with_invalid_disk_format(self):
         self.assertRaises(lib_exc.BadRequest, self.client.create_image,
@@ -41,7 +40,7 @@
                                    'x-image-meta-container_format': 'bare',
                                    'x-image-meta-disk_format': 'wrong'})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ec652588-7e3c-4b67-a2f2-0fa96f57c8fc')
     def test_delete_non_existent_image(self):
         # Return an error while trying to delete a non-existent image
@@ -50,13 +49,13 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           non_existent_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('04f72aa3-fcec-45a3-81a3-308ef7cc82bc')
     def test_delete_image_blank_id(self):
         # Return an error while trying to delete an image with blank Id
         self.assertRaises(lib_exc.NotFound, self.client.delete_image, '')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('950e5054-a3c7-4dee-ada5-e576f1087abd')
     def test_delete_image_non_hex_string_id(self):
         # Return an error while trying to delete an image with non hex id
@@ -64,13 +63,13 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           invalid_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4ed757cd-450c-44b1-9fd1-c819748c650d')
     def test_delete_image_negative_image_id(self):
         # Return an error while trying to delete an image with negative id
         self.assertRaises(lib_exc.NotFound, self.client.delete_image, -1)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a4a448ab-3db2-4d2d-b9b2-6a1271241dfe')
     def test_delete_image_id_over_character_limit(self):
         # Return an error while trying to delete image with id over limit
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 30f9ae2..8310001 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -23,7 +23,6 @@
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 LOG = logging.getLogger(__name__)
@@ -32,7 +31,7 @@
 class BasicOperationsImagesTest(base.BaseV2ImageTest):
     """Here we test the basic operations of images"""
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('139b765e-7f3d-4b3d-8b37-3ca3876ee318')
     def test_register_upload_get_image_file(self):
         """Here we test these functionalities
@@ -74,7 +73,7 @@
         body = self.client.show_image_file(image['id'])
         self.assertEqual(file_content, body.data)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f848bb94-1c6e-45a4-8726-39e3a5b23535')
     def test_delete_image(self):
         # Deletes an image by image_id
@@ -96,7 +95,7 @@
         images_id = [item['id'] for item in images]
         self.assertNotIn(image['id'], images_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f66891a7-a35c-41a8-b590-a065c2a1caa6')
     def test_update_image(self):
         # Updates an image by image_id
diff --git a/tempest/api/image/v2/test_images_member_negative.py b/tempest/api/image/v2/test_images_member_negative.py
index ae9630a..caa90f9 100644
--- a/tempest/api/image/v2/test_images_member_negative.py
+++ b/tempest/api/image/v2/test_images_member_negative.py
@@ -13,12 +13,11 @@
 from tempest.api.image import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ImagesMemberNegativeTest(base.BaseV2MemberImageTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b79efb37-820d-4cf0-b54c-308b00cf842c')
     def test_image_share_invalid_status(self):
         image_id = self._create_image()
@@ -30,7 +29,7 @@
                           image_id, self.alt_tenant_id,
                           status='notavalidstatus')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('27002f74-109e-4a37-acd0-f91cd4597967')
     def test_image_share_owner_cannot_accept(self):
         image_id = self._create_image()
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index 6e5e726..b4baf05 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -18,7 +18,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ImagesNegativeTest(base.BaseV2ImageTest):
@@ -34,7 +33,7 @@
         ** delete the deleted image
      """
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('668743d5-08ad-4480-b2b8-15da34f81d9f')
     def test_get_non_existent_image(self):
         # get the non-existent image
@@ -42,14 +41,14 @@
         self.assertRaises(lib_exc.NotFound, self.client.show_image,
                           non_existent_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ef45000d-0a72-4781-866d-4cb7bf2562ad')
     def test_get_image_null_id(self):
         # get image with image_id = NULL
         image_id = ""
         self.assertRaises(lib_exc.NotFound, self.client.show_image, image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e57fc127-7ba0-4693-92d7-1d8a05ebcba9')
     def test_get_delete_deleted_image(self):
         # get and delete the deleted image
@@ -68,7 +67,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           image['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6fe40f1c-57bd-4918-89cc-8500f850f3de')
     def test_delete_non_existing_image(self):
         # delete non-existent image
@@ -76,7 +75,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           non_existent_image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('32248db1-ab88-4821-9604-c7c369f1f88c')
     def test_delete_image_null_id(self):
         # delete image with image_id=NULL
@@ -84,7 +83,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.delete_image,
                           image_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('292bd310-369b-41c7-a7a3-10276ef76753')
     def test_register_with_invalid_container_format(self):
         # Negative tests for invalid data supplied to POST /images
@@ -92,14 +91,14 @@
                           name='test', container_format='wrong',
                           disk_format='vhd')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('70c6040c-5a97-4111-9e13-e73665264ce1')
     def test_register_with_invalid_disk_format(self):
         self.assertRaises(lib_exc.BadRequest, self.client.create_image,
                           name='test', container_format='bare',
                           disk_format='wrong')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ab980a34-8410-40eb-872b-f264752f46e5')
     def test_delete_protected_image(self):
         # Create a protected image
diff --git a/tempest/api/image/v2/test_images_tags_negative.py b/tempest/api/image/v2/test_images_tags_negative.py
index 7032dd4..440fa36 100644
--- a/tempest/api/image/v2/test_images_tags_negative.py
+++ b/tempest/api/image/v2/test_images_tags_negative.py
@@ -16,12 +16,11 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ImagesTagsNegativeTest(base.BaseV2ImageTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8cd30f82-6f9a-4c6e-8034-c1b51fba43d9')
     def test_update_tags_for_non_existing_image(self):
         # Update tag with non existing image.
@@ -30,7 +29,7 @@
         self.assertRaises(lib_exc.NotFound, self.client.add_image_tag,
                           non_exist_image, tag)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('39c023a2-325a-433a-9eea-649bf1414b19')
     def test_delete_non_existing_tag(self):
         # Delete non existing tag.
diff --git a/tempest/api/image/v2/test_versions.py b/tempest/api/image/v2/test_versions.py
index 24f104c..84f1068 100644
--- a/tempest/api/image/v2/test_versions.py
+++ b/tempest/api/image/v2/test_versions.py
@@ -14,13 +14,12 @@
 
 from tempest.api.image import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class VersionsTest(base.BaseV2ImageTest):
 
     @decorators.idempotent_id('659ea30a-a17c-4317-832c-0f68ed23c31d')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     def test_list_versions(self):
         versions = self.versions_client.list_versions()['versions']
         expected_resources = ('id', 'links', 'status')
diff --git a/tempest/api/network/admin/test_external_networks_negative.py b/tempest/api/network/admin/test_external_networks_negative.py
index 770d91f..0709d2a 100644
--- a/tempest/api/network/admin/test_external_networks_negative.py
+++ b/tempest/api/network/admin/test_external_networks_negative.py
@@ -19,14 +19,13 @@
 from tempest.lib.common.utils import test_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
 
 class ExternalNetworksAdminNegativeTestJSON(base.BaseAdminNetworkTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d402ae6c-0be0-4d8e-833b-a738895d98d0')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
diff --git a/tempest/api/network/admin/test_negative_quotas.py b/tempest/api/network/admin/test_negative_quotas.py
index 2c639da..21688d2 100644
--- a/tempest/api/network/admin/test_negative_quotas.py
+++ b/tempest/api/network/admin/test_negative_quotas.py
@@ -39,7 +39,7 @@
             msg = "quotas extension not enabled."
             raise cls.skipException(msg)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('644f4e1b-1bf9-4af0-9fd8-eb56ac0f51cf')
     def test_network_quota_exceeding(self):
         # Set the network quota to two
diff --git a/tempest/api/network/test_extensions.py b/tempest/api/network/test_extensions.py
index 2662e9c..014d064 100644
--- a/tempest/api/network/test_extensions.py
+++ b/tempest/api/network/test_extensions.py
@@ -29,7 +29,7 @@
     etc/tempest.conf.
     """
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('ef28c7e6-e646-4979-9d67-deb207bc5564')
     def test_list_show_extensions(self):
         # List available extensions for the project
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index 1dc574b..f0f92ac 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -64,7 +64,7 @@
         for i in range(2):
             cls.create_port(cls.network)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('62595970-ab1c-4b7f-8fcc-fddfe55e8718')
     def test_create_list_show_update_delete_floating_ip(self):
         # Creates a floating IP
@@ -171,7 +171,7 @@
                          port_other_router['id'])
         self.assertIsNotNone(updated_floating_ip['fixed_ip_address'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('36de4bd0-f09c-43e3-a8e1-1decc1ffd3a5')
     def test_create_floating_ip_specifying_a_fixed_ip_address(self):
         body = self.floating_ips_client.create_floatingip(
diff --git a/tempest/api/network/test_floating_ips_negative.py b/tempest/api/network/test_floating_ips_negative.py
index cb29d3d..f5830ab 100644
--- a/tempest/api/network/test_floating_ips_negative.py
+++ b/tempest/api/network/test_floating_ips_negative.py
@@ -52,7 +52,7 @@
         cls.create_router_interface(router['id'], subnet['id'])
         cls.port = cls.create_port(cls.network)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('22996ea8-4a81-4b27-b6e1-fa5df92fa5e8')
     def test_create_floatingip_with_port_ext_net_unreachable(self):
         self.assertRaises(
@@ -61,7 +61,7 @@
             fixed_ip_address=self.port['fixed_ips'][0]
                                       ['ip_address'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('50b9aeb4-9f0b-48ee-aa31-fa955a48ff54')
     def test_create_floatingip_in_private_network(self):
         self.assertRaises(lib_exc.BadRequest,
@@ -71,7 +71,7 @@
                           fixed_ip_address=self.port['fixed_ips'][0]
                                                     ['ip_address'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6b3b8797-6d43-4191-985c-c48b773eb429')
     def test_associate_floatingip_port_ext_net_unreachable(self):
         # Create floating ip
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index fc9f465..269f2c2 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -174,7 +174,7 @@
         project_network_v6_mask_bits is the equivalent for ipv6 subnets
     """
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('0e269138-0da6-4efc-a46d-578161e7b221')
     def test_create_update_delete_network_subnet(self):
         # Create a network
@@ -196,7 +196,7 @@
         updated_subnet = body['subnet']
         self.assertEqual(updated_subnet['name'], new_name)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2bf13842-c93f-4a69-83ed-717d2ec3b44e')
     def test_show_network(self):
         # Verify the details of a network
@@ -220,7 +220,7 @@
         self.assertNotIn('tenant_id', network)
         self.assertNotIn('project_id', network)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f7ffdeda-e200-4a7a-bcbe-05716e86bf43')
     def test_list_networks(self):
         # Verify the network exists in the list of all networks
@@ -241,7 +241,7 @@
         for network in networks:
             self.assertEqual(sorted(network.keys()), sorted(fields))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('bd635d81-6030-4dd1-b3b9-31ba0cfdf6cc')
     def test_show_subnet(self):
         # Verify the details of a subnet
@@ -263,7 +263,7 @@
         for field_name in fields:
             self.assertEqual(subnet[field_name], self.subnet[field_name])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('db68ba48-f4ea-49e9-81d1-e367f6d0b20a')
     def test_list_subnets(self):
         # Verify the subnet exists in the list of all subnets
@@ -368,7 +368,7 @@
             enable_dhcp=True,
             **self.subnet_dict(['gateway', 'host_routes', 'dns_nameservers']))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('af774677-42a9-4e4b-bb58-16fe6a5bc1ec')
     @test.requires_ext(extension='external-net', service='network')
     @testtools.skipUnless(CONF.network.public_network_id,
@@ -452,7 +452,7 @@
         for n in created_ports:
             self.assertNotIn(n['id'], ports_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('d4f9024d-1e28-4fc1-a6b1-25dbc6fa11e2')
     def test_bulk_create_delete_network(self):
         # Creates 2 networks in one request
@@ -468,7 +468,7 @@
             self.assertIsNotNone(n['id'])
             self.assertIn(n['id'], networks_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('8936533b-c0aa-4f29-8e53-6cc873aec489')
     def test_bulk_create_delete_subnet(self):
         networks = [self.create_network(), self.create_network()]
@@ -503,7 +503,7 @@
             self.assertIsNotNone(n['id'])
             self.assertIn(n['id'], subnets_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('48037ff2-e889-4c3b-b86a-8e3f34d2d060')
     def test_bulk_create_delete_port(self):
         networks = [self.create_network(), self.create_network()]
diff --git a/tempest/api/network/test_networks_negative.py b/tempest/api/network/test_networks_negative.py
index 5cb12fe..bc4f41f 100644
--- a/tempest/api/network/test_networks_negative.py
+++ b/tempest/api/network/test_networks_negative.py
@@ -18,33 +18,32 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class NetworksNegativeTestJSON(base.BaseNetworkTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9293e937-824d-42d2-8d5b-e985ea67002a')
     def test_show_non_existent_network(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.networks_client.show_network,
                           non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('d746b40c-5e09-4043-99f7-cba1be8b70df')
     def test_show_non_existent_subnet(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.subnets_client.show_subnet,
                           non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a954861d-cbfd-44e8-b0a9-7fab111f235d')
     def test_show_non_existent_port(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.ports_client.show_port,
                           non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('98bfe4e3-574e-4012-8b17-b2647063de87')
     def test_update_non_existent_network(self):
         non_exist_id = data_utils.rand_uuid()
@@ -52,7 +51,7 @@
             lib_exc.NotFound, self.networks_client.update_network,
             non_exist_id, name="new_name")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('03795047-4a94-4120-a0a1-bd376e36fd4e')
     def test_delete_non_existent_network(self):
         non_exist_id = data_utils.rand_uuid()
@@ -60,21 +59,21 @@
                           self.networks_client.delete_network,
                           non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1cc47884-ac52-4415-a31c-e7ce5474a868')
     def test_update_non_existent_subnet(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.subnets_client.update_subnet,
                           non_exist_id, name='new_name')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a176c859-99fb-42ec-a208-8a85b552a239')
     def test_delete_non_existent_subnet(self):
         non_exist_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound,
                           self.subnets_client.delete_subnet, non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('13d3b106-47e6-4b9b-8d53-dae947f092fe')
     def test_create_port_on_non_existent_network(self):
         non_exist_net_id = data_utils.rand_uuid()
@@ -82,14 +81,14 @@
                           self.ports_client.create_port,
                           network_id=non_exist_net_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('cf8eef21-4351-4f53-adcd-cc5cb1e76b92')
     def test_update_non_existent_port(self):
         non_exist_port_id = data_utils.rand_uuid()
         self.assertRaises(lib_exc.NotFound, self.ports_client.update_port,
                           non_exist_port_id, name='new_name')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('49ec2bbd-ac2e-46fd-8054-798e679ff894')
     def test_delete_non_existent_port(self):
         non_exist_port_id = data_utils.rand_uuid()
diff --git a/tempest/api/network/test_ports.py b/tempest/api/network/test_ports.py
index 376d4ae..69a1441 100644
--- a/tempest/api/network/test_ports.py
+++ b/tempest/api/network/test_ports.py
@@ -52,7 +52,7 @@
         ports_list = body['ports']
         self.assertFalse(port_id in [n['id'] for n in ports_list])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('c72c1c0c-2193-4aca-aaa4-b1442640f51c')
     def test_create_update_delete_port(self):
         # Verify port creation
@@ -100,7 +100,7 @@
 
         return cidr
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('0435f278-40ae-48cb-a404-b8a087bc09b1')
     def test_create_port_in_allowed_allocation_pools(self):
         network = self.create_network()
@@ -125,7 +125,7 @@
         ip_range = netaddr.IPRange(start_ip_address, end_ip_address)
         self.assertIn(ip_address, ip_range)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('c9a685bd-e83f-499c-939f-9f7863ca259f')
     def test_show_port(self):
         # Verify the details of port
@@ -153,7 +153,7 @@
         for field_name in fields:
             self.assertEqual(port[field_name], self.port[field_name])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('cf95b358-3e92-4a29-a148-52445e1ac50e')
     def test_list_ports(self):
         # Verify the port exists in the list of all ports
@@ -342,7 +342,7 @@
         self.assertEqual(free_mac_address,
                          show_port['mac_address'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('4179dcb9-1382-4ced-84fe-1b91c54f5735')
     @testtools.skipUnless(
         test.is_extension_enabled('security-group', 'network'),
diff --git a/tempest/api/network/test_routers.py b/tempest/api/network/test_routers.py
index 8df5248..97ad4d4 100644
--- a/tempest/api/network/test_routers.py
+++ b/tempest/api/network/test_routers.py
@@ -41,7 +41,7 @@
                            if cls._ip_version == 4 else
                            CONF.network.project_network_v6_cidr)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f64403e2-8483-4b34-8ccd-b09a87bcc68c')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
@@ -122,7 +122,7 @@
             self._verify_router_gateway(create_body['router']['id'],
                                         exp_ext_gw_info=external_gateway_info)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('b42e6e39-2e37-49cc-a6f4-8467e940900a')
     def test_add_remove_router_interface_with_subnet_id(self):
         network = self.create_network()
@@ -141,7 +141,7 @@
         self.assertEqual(show_port_body['port']['device_id'],
                          router['id'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2b7d2f37-6748-4d78-92e5-1d590234f0d5')
     def test_add_remove_router_interface_with_port_id(self):
         network = self.create_network()
@@ -376,7 +376,7 @@
         show_body = self.routers_client.show_router(router['id'])
         self.assertTrue(show_body['router']['admin_state_up'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('802c73c9-c937-4cef-824b-2191e24a6aab')
     def test_add_multiple_router_interfaces(self):
         network01 = self.create_network(
diff --git a/tempest/api/network/test_routers_negative.py b/tempest/api/network/test_routers_negative.py
index 8d680e9..fdd8dd8 100644
--- a/tempest/api/network/test_routers_negative.py
+++ b/tempest/api/network/test_routers_negative.py
@@ -45,7 +45,7 @@
                            if cls._ip_version == 4 else
                            CONF.network.project_network_v6_cidr)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('37a94fc0-a834-45b9-bd23-9a81d2fd1e22')
     def test_router_add_gateway_invalid_network_returns_404(self):
         self.assertRaises(lib_exc.NotFound,
@@ -54,7 +54,7 @@
                           external_gateway_info={
                               'network_id': self.router['id']})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('11836a18-0b15-4327-a50b-f0d9dc66bddd')
     def test_router_add_gateway_net_not_external_returns_400(self):
         alt_network = self.create_network()
@@ -66,7 +66,7 @@
                           external_gateway_info={
                               'network_id': alt_network['id']})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('957751a3-3c68-4fa2-93b6-eb52ea10db6e')
     def test_add_router_interfaces_on_overlapping_subnets_returns_400(self):
         network01 = self.create_network(
@@ -82,7 +82,7 @@
                           self.router['id'],
                           subnet02['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7101cc02-058a-11e7-93e1-fa163e4fa634')
     @test.requires_ext(extension='ext-gw-mode', service='network')
     @testtools.skipUnless(CONF.network.public_network_id,
@@ -107,7 +107,7 @@
                           self.admin_routers_client.create_router,
                           external_gateway_info=external_gateway_info)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('04df80f9-224d-47f5-837a-bf23e33d1c20')
     def test_router_remove_interface_in_use_returns_409(self):
         self.routers_client.add_router_interface(self.router['id'],
@@ -116,21 +116,21 @@
                           self.routers_client.delete_router,
                           self.router['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c2a70d72-8826-43a7-8208-0209e6360c47')
     def test_show_non_existent_router_returns_404(self):
         router = data_utils.rand_name('non_exist_router')
         self.assertRaises(lib_exc.NotFound, self.routers_client.show_router,
                           router)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b23d1569-8b0c-4169-8d4b-6abd34fad5c7')
     def test_update_non_existent_router_returns_404(self):
         router = data_utils.rand_name('non_exist_router')
         self.assertRaises(lib_exc.NotFound, self.routers_client.update_router,
                           router, name="new_name")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c7edc5ad-d09d-41e6-a344-5c0c31e2e3e4')
     def test_delete_non_existent_router_returns_404(self):
         router = data_utils.rand_name('non_exist_router')
@@ -158,7 +158,7 @@
         cls.network = cls.create_network()
         cls.subnet = cls.create_subnet(cls.network)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4990b055-8fc7-48ab-bba7-aa28beaad0b9')
     def test_router_create_tenant_distributed_returns_forbidden(self):
         self.assertRaises(lib_exc.Forbidden, self.create_router,
diff --git a/tempest/api/network/test_security_groups.py b/tempest/api/network/test_security_groups.py
index d7e5149..0d5e230 100644
--- a/tempest/api/network/test_security_groups.py
+++ b/tempest/api/network/test_security_groups.py
@@ -67,7 +67,7 @@
                              "rule does not match with %s." %
                              (key, value))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('e30abd17-fef9-4739-8617-dc26da88e686')
     def test_list_security_groups(self):
         # Verify the security group belonging to project exist in list
@@ -80,7 +80,7 @@
         msg = "Security-group list doesn't contain default security-group"
         self.assertIsNotNone(found, msg)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('bfd128e5-3c92-44b6-9d66-7fe29d22c802')
     def test_create_list_update_show_delete_security_group(self):
         group_create_body, name = self._create_security_group()
@@ -109,7 +109,7 @@
         self.assertEqual(show_body['security_group']['description'],
                          new_description)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('cfb99e0e-7410-4a3d-8a0c-959a63ee77e9')
     def test_create_show_delete_security_group_rule(self):
         group_create_body, _ = self._create_security_group()
diff --git a/tempest/api/network/test_security_groups_negative.py b/tempest/api/network/test_security_groups_negative.py
index 218a79a..f51fb33 100644
--- a/tempest/api/network/test_security_groups_negative.py
+++ b/tempest/api/network/test_security_groups_negative.py
@@ -33,7 +33,7 @@
             msg = "security-group extension not enabled."
             raise cls.skipException(msg)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('424fd5c3-9ddc-486a-b45f-39bf0c820fc6')
     def test_show_non_existent_security_group(self):
         non_exist_id = data_utils.rand_uuid()
@@ -41,7 +41,7 @@
             lib_exc.NotFound, self.security_groups_client.show_security_group,
             non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4c094c09-000b-4e41-8100-9617600c02a6')
     def test_show_non_existent_security_group_rule(self):
         non_exist_id = data_utils.rand_uuid()
@@ -50,7 +50,7 @@
             self.security_group_rules_client.show_security_group_rule,
             non_exist_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1f1bb89d-5664-4956-9fcd-83ee0fa603df')
     def test_delete_non_existent_security_group(self):
         non_exist_id = data_utils.rand_uuid()
@@ -59,7 +59,7 @@
                           non_exist_id
                           )
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('981bdc22-ce48-41ed-900a-73148b583958')
     def test_create_security_group_rule_with_bad_protocol(self):
         group_create_body, _ = self._create_security_group()
@@ -72,7 +72,7 @@
             security_group_id=group_create_body['security_group']['id'],
             protocol=pname, direction='ingress', ethertype=self.ethertype)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5f8daf69-3c5f-4aaa-88c9-db1d66f68679')
     def test_create_security_group_rule_with_bad_remote_ip_prefix(self):
         group_create_body, _ = self._create_security_group()
@@ -87,7 +87,7 @@
                 protocol='tcp', direction='ingress', ethertype=self.ethertype,
                 remote_ip_prefix=remote_ip_prefix)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('4bf786fd-2f02-443c-9716-5b98e159a49a')
     def test_create_security_group_rule_with_non_existent_remote_groupid(self):
         group_create_body, _ = self._create_security_group()
@@ -103,7 +103,7 @@
                 protocol='tcp', direction='ingress', ethertype=self.ethertype,
                 remote_group_id=remote_group_id)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b5c4b247-6b02-435b-b088-d10d45650881')
     def test_create_security_group_rule_with_remote_ip_and_group(self):
         sg1_body, _ = self._create_security_group()
@@ -119,7 +119,7 @@
             ethertype=self.ethertype, remote_ip_prefix=prefix,
             remote_group_id=sg2_body['security_group']['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5666968c-fff3-40d6-9efc-df1c8bd01abb')
     def test_create_security_group_rule_with_bad_ethertype(self):
         group_create_body, _ = self._create_security_group()
@@ -132,7 +132,7 @@
             security_group_id=group_create_body['security_group']['id'],
             protocol='udp', direction='ingress', ethertype=ethertype)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0d9c7791-f2ad-4e2f-ac73-abf2373b0d2d')
     def test_create_security_group_rule_with_invalid_ports(self):
         group_create_body, _ = self._create_security_group()
@@ -166,7 +166,7 @@
                 direction='ingress', ethertype=self.ethertype)
             self.assertIn(msg, str(ex))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('2323061e-9fbf-4eb0-b547-7e8fafc90849')
     def test_create_additional_default_security_group_fails(self):
         # Create security group named 'default', it should be failed.
@@ -175,7 +175,7 @@
                           self.security_groups_client.create_security_group,
                           name=name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('966e2b96-023a-11e7-a9e4-fa163e4fa634')
     def test_create_security_group_update_name_default(self):
         # Update security group name to 'default', it should be failed.
@@ -185,7 +185,7 @@
                           group_create_body['security_group']['id'],
                           name="default")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8fde898f-ce88-493b-adc9-4e4692879fc5')
     def test_create_duplicate_security_group_rule_fails(self):
         # Create duplicate security group rule, it should fail.
@@ -211,7 +211,7 @@
             protocol='tcp', direction='ingress', ethertype=self.ethertype,
             port_range_min=min_port, port_range_max=max_port)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('be308db6-a7cf-4d5c-9baf-71bafd73f35e')
     def test_create_security_group_rule_with_non_existent_security_group(self):
         # Create security group rules with not existing security group.
@@ -227,7 +227,7 @@
     _ip_version = 6
     _project_network_cidr = CONF.network.project_network_v6_cidr
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7607439c-af73-499e-bf64-f687fd12a842')
     def test_create_security_group_rule_wrong_ip_prefix_version(self):
         group_create_body, _ = self._create_security_group()
diff --git a/tempest/api/network/test_subnetpools_extensions.py b/tempest/api/network/test_subnetpools_extensions.py
index be6bffc..01d7db2 100644
--- a/tempest/api/network/test_subnetpools_extensions.py
+++ b/tempest/api/network/test_subnetpools_extensions.py
@@ -46,7 +46,7 @@
             msg = "subnet_allocation extension not enabled."
             raise cls.skipException(msg)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('62595970-ab1c-4b7f-8fcc-fddfe55e9811')
     def test_create_list_show_update_delete_subnetpools(self):
         subnetpool_name = data_utils.rand_name('subnetpools')
diff --git a/tempest/api/network/test_versions.py b/tempest/api/network/test_versions.py
index 4f6d5ac..2f01e50 100644
--- a/tempest/api/network/test_versions.py
+++ b/tempest/api/network/test_versions.py
@@ -14,11 +14,10 @@
 
 from tempest.api.network import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class NetworksApiDiscovery(base.BaseNetworkTest):
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('cac8a836-c2e0-4304-b556-cd299c7281d1')
     def test_api_version_resources(self):
         """Test that GET / returns expected resources.
diff --git a/tempest/api/object_storage/test_account_quotas.py b/tempest/api/object_storage/test_account_quotas.py
index 84e4508..9077f88 100644
--- a/tempest/api/object_storage/test_account_quotas.py
+++ b/tempest/api/object_storage/test_account_quotas.py
@@ -76,7 +76,7 @@
         cls.delete_containers()
         super(AccountQuotasTest, cls).resource_cleanup()
 
-    @test.attr(type="smoke")
+    @decorators.attr(type="smoke")
     @decorators.idempotent_id('a22ef352-a342-4587-8f47-3bbdb5b039c4')
     @test.requires_ext(extension='account_quotas', service='object')
     def test_upload_valid_object(self):
@@ -87,7 +87,7 @@
 
         self.assertHeaders(resp, 'Object', 'PUT')
 
-    @test.attr(type=["smoke"])
+    @decorators.attr(type=["smoke"])
     @decorators.idempotent_id('63f51f9f-5f1d-4fc6-b5be-d454d70949d6')
     @test.requires_ext(extension='account_quotas', service='object')
     def test_admin_modify_quota(self):
diff --git a/tempest/api/object_storage/test_account_quotas_negative.py b/tempest/api/object_storage/test_account_quotas_negative.py
index 2e85a43..6784a55 100644
--- a/tempest/api/object_storage/test_account_quotas_negative.py
+++ b/tempest/api/object_storage/test_account_quotas_negative.py
@@ -75,7 +75,7 @@
         cls.delete_containers()
         super(AccountQuotasNegativeTest, cls).resource_cleanup()
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('d1dc5076-555e-4e6d-9697-28f1fe976324')
     @test.requires_ext(extension='account_quotas', service='object')
     def test_user_modify_quota(self):
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index de64dfe..d0a3f10 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -23,7 +23,6 @@
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 
@@ -54,7 +53,7 @@
         cls.delete_containers()
         super(AccountTest, cls).resource_cleanup()
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('3499406a-ae53-4f8c-b43a-133d4dc6fe3f')
     def test_list_containers(self):
         # list of all containers should not be empty
@@ -265,7 +264,7 @@
         self.assertEqual(sorted(orig_container_list, reverse=True),
                          container_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('4894c312-6056-4587-8d6f-86ffbf861f80')
     def test_list_account_metadata(self):
         # list all account metadata
diff --git a/tempest/api/object_storage/test_account_services_negative.py b/tempest/api/object_storage/test_account_services_negative.py
index d46534b..e98a4f5 100644
--- a/tempest/api/object_storage/test_account_services_negative.py
+++ b/tempest/api/object_storage/test_account_services_negative.py
@@ -16,7 +16,6 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -32,7 +31,7 @@
         cls.os = cls.os_roles_operator
         cls.os_operator = cls.os_roles_operator_alt
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('070e6aca-6152-4867-868d-1118d68fb38c')
     def test_list_containers_with_non_authorized_user(self):
         # list containers using non-authorized user
diff --git a/tempest/api/object_storage/test_container_acl_negative.py b/tempest/api/object_storage/test_container_acl_negative.py
index c0f7b3a..9c9d821 100644
--- a/tempest/api/object_storage/test_container_acl_negative.py
+++ b/tempest/api/object_storage/test_container_acl_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -47,7 +46,7 @@
         self.delete_containers([self.container_name])
         super(ObjectACLsNegativeTest, self).tearDown()
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('af587587-0c24-4e15-9822-8352ce711013')
     def test_write_object_without_using_creds(self):
         # trying to create object with empty headers
@@ -61,7 +60,7 @@
                           self.object_client.create_object,
                           self.container_name, object_name, 'data', headers={})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('af85af0b-a025-4e72-a90e-121babf55720')
     def test_delete_object_without_using_creds(self):
         # create object
@@ -78,7 +77,7 @@
                           self.object_client.delete_object,
                           self.container_name, object_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('63d84e37-55a6-42e2-9e5f-276e60e26a00')
     def test_write_object_with_non_authorized_user(self):
         # attempt to upload another file using non-authorized user
@@ -93,7 +92,7 @@
                           self.object_client.create_object,
                           self.container_name, object_name, 'data', headers={})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('abf63359-be52-4feb-87dd-447689fc77fd')
     def test_read_object_with_non_authorized_user(self):
         # attempt to read object using non-authorized user
@@ -111,7 +110,7 @@
                           self.object_client.get_object,
                           self.container_name, object_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('7343ac3d-cfed-4198-9bb0-00149741a492')
     def test_delete_object_with_non_authorized_user(self):
         # attempt to delete object using non-authorized user
@@ -129,7 +128,7 @@
                           self.object_client.delete_object,
                           self.container_name, object_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9ed01334-01e9-41ea-87ea-e6f465582823')
     def test_read_object_without_rights(self):
         # attempt to read object using non-authorized user
@@ -153,7 +152,7 @@
                           self.object_client.get_object,
                           self.container_name, object_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a3a585a7-d8cf-4b65-a1a0-edc2b1204f85')
     def test_write_object_without_rights(self):
         # attempt to write object using non-authorized user
@@ -174,7 +173,7 @@
                           self.container_name,
                           object_name, 'data', headers={})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8ba512ad-aa6e-444e-b882-2906a0ea2052')
     def test_write_object_without_write_rights(self):
         # attempt to write object using non-authorized user
@@ -199,7 +198,7 @@
                           self.container_name,
                           object_name, 'data', headers={})
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b4e366f8-f185-47ab-b789-df4416f9ecdb')
     def test_delete_object_without_write_rights(self):
         # attempt to delete object using non-authorized user
diff --git a/tempest/api/object_storage/test_container_quotas.py b/tempest/api/object_storage/test_container_quotas.py
index 7ff337e..8266341 100644
--- a/tempest/api/object_storage/test_container_quotas.py
+++ b/tempest/api/object_storage/test_container_quotas.py
@@ -50,7 +50,7 @@
 
     @decorators.idempotent_id('9a0fb034-86af-4df0-86fa-f8bd7db21ae0')
     @test.requires_ext(extension='container_quotas', service='object')
-    @test.attr(type="smoke")
+    @decorators.attr(type="smoke")
     def test_upload_valid_object(self):
         """Attempts to uploads an object smaller than the bytes quota."""
         object_name = data_utils.rand_name(name="TestObject")
@@ -67,7 +67,7 @@
 
     @decorators.idempotent_id('22eeeb2b-3668-4160-baef-44790f65a5a0')
     @test.requires_ext(extension='container_quotas', service='object')
-    @test.attr(type="smoke")
+    @decorators.attr(type="smoke")
     def test_upload_large_object(self):
         """Attempts to upload an object larger than the bytes quota."""
         object_name = data_utils.rand_name(name="TestObject")
@@ -84,7 +84,7 @@
 
     @decorators.idempotent_id('3a387039-697a-44fc-a9c0-935de31f426b')
     @test.requires_ext(extension='container_quotas', service='object')
-    @test.attr(type="smoke")
+    @decorators.attr(type="smoke")
     def test_upload_too_many_objects(self):
         """Attempts to upload many objects that exceeds the count limit."""
         for _ in range(QUOTA_COUNT):
diff --git a/tempest/api/object_storage/test_container_services.py b/tempest/api/object_storage/test_container_services.py
index a82d2cc..2b5692d 100644
--- a/tempest/api/object_storage/test_container_services.py
+++ b/tempest/api/object_storage/test_container_services.py
@@ -16,7 +16,6 @@
 from tempest.api.object_storage import base
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class ContainerTest(base.BaseObjectTest):
@@ -24,7 +23,7 @@
         self.delete_containers()
         super(ContainerTest, self).tearDown()
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('92139d73-7819-4db1-85f8-3f2f22a8d91f')
     def test_create_container(self):
         container_name = data_utils.rand_name(name='TestContainer')
@@ -124,7 +123,7 @@
         resp, _ = self.container_client.delete_container(container_name)
         self.assertHeaders(resp, 'Container', 'DELETE')
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('312ff6bd-5290-497f-bda1-7c5fec6697ab')
     def test_list_container_contents(self):
         # get container contents list
@@ -271,7 +270,7 @@
         self.assertHeaders(resp, 'Container', 'GET')
         self.assertEqual([object_name], object_list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('96e68f0e-19ec-4aa2-86f3-adc6a45e14dd')
     def test_list_container_metadata(self):
         # List container metadata
diff --git a/tempest/api/object_storage/test_container_services_negative.py b/tempest/api/object_storage/test_container_services_negative.py
index be066ba..a8d70c5 100644
--- a/tempest/api/object_storage/test_container_services_negative.py
+++ b/tempest/api/object_storage/test_container_services_negative.py
@@ -20,7 +20,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions
-from tempest import test
 
 CONF = config.CONF
 
@@ -36,7 +35,7 @@
             _, body = cls.capabilities_client.list_capabilities()
             cls.constraints = body['swift']
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('30686921-4bed-4764-a038-40d741ed4e78')
     @testtools.skipUnless(
         CONF.object_storage_feature_enabled.discoverability,
@@ -52,7 +51,7 @@
         self.assertIn('Container name length of ' + str(max_length + 1) +
                       ' longer than ' + str(max_length), str(ex))
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('41e645bf-2e68-4f84-bf7b-c71aa5cd76ce')
     @testtools.skipUnless(
         CONF.object_storage_feature_enabled.discoverability,
@@ -69,7 +68,7 @@
                                container_name, metadata=metadata)
         self.assertIn('Metadata name too long', str(ex))
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('81e36922-326b-4b7c-8155-3bbceecd7a82')
     @testtools.skipUnless(
         CONF.object_storage_feature_enabled.discoverability,
@@ -86,7 +85,7 @@
                                container_name, metadata=metadata)
         self.assertIn('Metadata value longer than ' + str(max_length), str(ex))
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('ac666539-d566-4f02-8ceb-58e968dfb732')
     @testtools.skipUnless(
         CONF.object_storage_feature_enabled.discoverability,
@@ -106,7 +105,7 @@
         self.assertIn('Too many metadata items; max ' + str(max_count),
                       str(ex))
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('1a95ab2e-b712-4a98-8a4d-8ce21b7557d6')
     def test_get_metadata_headers_with_invalid_container_name(self):
         # Attempts to retrieve metadata headers with an invalid
@@ -115,7 +114,7 @@
                           self.container_client.list_container_metadata,
                           'invalid_container_name')
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('125a24fa-90a7-4cfc-b604-44e49d788390')
     def test_update_metadata_with_nonexistent_container_name(self):
         # Attempts to update metadata using a nonexistent container name.
@@ -125,7 +124,7 @@
                           self.container_client.update_container_metadata,
                           'nonexistent_container_name', metadata)
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('65387dbf-a0e2-4aac-9ddc-16eb3f1f69ba')
     def test_delete_with_nonexistent_container_name(self):
         # Attempts to delete metadata using a nonexistent container name.
@@ -135,7 +134,7 @@
                           self.container_client.delete_container_metadata,
                           'nonexistent_container_name', metadata)
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('14331d21-1e81-420a-beea-19cb5e5207f5')
     def test_list_all_container_objects_with_nonexistent_container(self):
         # Attempts to get a listing of all objects on a container
@@ -145,7 +144,7 @@
                           self.container_client.list_container_contents,
                           'nonexistent_container_name', params)
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('86b2ab08-92d5-493d-acd2-85f0c848819e')
     def test_list_all_container_objects_on_deleted_container(self):
         # Attempts to get a listing of all objects on a container
@@ -159,7 +158,7 @@
                           self.container_client.list_container_contents,
                           container_name, params)
 
-    @test.attr(type=["negative"])
+    @decorators.attr(type=["negative"])
     @decorators.idempotent_id('42da116e-1e8c-4c96-9e06-2f13884ed2b1')
     def test_delete_non_empty_container(self):
         # create a container and an object within it
diff --git a/tempest/api/object_storage/test_container_sync.py b/tempest/api/object_storage/test_container_sync.py
index 1c45a98..3c11a51 100644
--- a/tempest/api/object_storage/test_container_sync.py
+++ b/tempest/api/object_storage/test_container_sync.py
@@ -22,7 +22,6 @@
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 
@@ -128,7 +127,7 @@
                 resp, object_content = obj_client.get_object(cont, obj_name)
                 self.assertEqual(object_content, obj_name[::-1].encode())
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.skip_because(bug='1317133')
     @decorators.idempotent_id('be008325-1bba-4925-b7dd-93b58f22ce9b')
     @testtools.skipIf(
diff --git a/tempest/api/object_storage/test_container_sync_middleware.py b/tempest/api/object_storage/test_container_sync_middleware.py
index df738b3..9eae138 100644
--- a/tempest/api/object_storage/test_container_sync_middleware.py
+++ b/tempest/api/object_storage/test_container_sync_middleware.py
@@ -37,7 +37,7 @@
         cls.key = 'sync_key'
         cls.cluster_name = CONF.object_storage.cluster_name
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('ea4645a1-d147-4976-82f7-e5a7a3065f80')
     @test.requires_ext(extension='container_sync', service='object')
     def test_container_synchronization(self):
diff --git a/tempest/api/object_storage/test_object_formpost_negative.py b/tempest/api/object_storage/test_object_formpost_negative.py
index c4e6a3a..cfa1875 100644
--- a/tempest/api/object_storage/test_object_formpost_negative.py
+++ b/tempest/api/object_storage/test_object_formpost_negative.py
@@ -108,7 +108,7 @@
 
     @decorators.idempotent_id('d3fb3c4d-e627-48ce-9379-a1631f21336d')
     @test.requires_ext(extension='formpost', service='object')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_post_object_using_form_expired(self):
         body, content_type = self.get_multipart_form(expires=1)
         time.sleep(2)
@@ -125,7 +125,7 @@
 
     @decorators.idempotent_id('b277257f-113c-4499-b8d1-5fead79f7360')
     @test.requires_ext(extension='formpost', service='object')
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     def test_post_object_using_form_invalid_signature(self):
         self.key = "Wrong"
         body, content_type = self.get_multipart_form()
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index d463827..21ea6ae 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -24,7 +24,6 @@
 from tempest import config
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 CONF = config.CONF
 
@@ -75,7 +74,7 @@
             for meta_key in not_in_meta:
                 self.assertNotIn('x-object-meta-' + meta_key, resp)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('5b4ce26f-3545-46c9-a2ba-5754358a4c62')
     def test_create_object(self):
         # create object
@@ -319,7 +318,7 @@
                                                    object_name)
         self.assertHeaders(resp, 'Object', 'DELETE')
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('7a94c25d-66e6-434c-9c38-97d4e2c29945')
     def test_update_object_metadata(self):
         # update object metadata
@@ -460,7 +459,7 @@
             object_name)
         self.assertNotIn('x-object-meta-test-meta', resp)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('9a447cf6-de06-48de-8226-a8c6ed31caf2')
     def test_list_object_metadata(self):
         # get object metadata
@@ -530,7 +529,7 @@
         self.assertEqual(resp['x-object-manifest'],
                          '%s/%s' % (self.container_name, object_name))
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('02610ba7-86b7-4272-9ed8-aa8d417cb3cd')
     def test_get_object(self):
         # retrieve object's data (in response body)
diff --git a/tempest/api/object_storage/test_object_temp_url_negative.py b/tempest/api/object_storage/test_object_temp_url_negative.py
index 9c1393f..578249b 100644
--- a/tempest/api/object_storage/test_object_temp_url_negative.py
+++ b/tempest/api/object_storage/test_object_temp_url_negative.py
@@ -91,7 +91,7 @@
 
         return url
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5a583aca-c804-41ba-9d9a-e7be132bdf0b')
     @test.requires_ext(extension='tempurl', service='object')
     def test_get_object_after_expiration_time(self):
diff --git a/tempest/api/orchestration/stacks/test_resource_types.py b/tempest/api/orchestration/stacks/test_resource_types.py
index 63376d5..6d0707e 100644
--- a/tempest/api/orchestration/stacks/test_resource_types.py
+++ b/tempest/api/orchestration/stacks/test_resource_types.py
@@ -12,12 +12,11 @@
 
 from tempest.api.orchestration import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class ResourceTypesTest(base.BaseOrchestrationTest):
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('7123d082-3577-4a30-8f00-f805327c4ffd')
     def test_resource_type_list(self):
         """Verify it is possible to list resource types."""
@@ -25,7 +24,7 @@
         self.assertIsInstance(resource_types, list)
         self.assertIn('OS::Nova::Server', resource_types)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('0e85a483-828b-4a28-a0e3-f0a21809192b')
     def test_resource_type_show(self):
         """Verify it is possible to get schema about resource types."""
@@ -38,7 +37,7 @@
                                        'attributes', 'resource_type')
             self.assertEqual(resource_type, type_schema['resource_type'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('8401821d-65fe-4d43-9fa3-57d5ce3a35c7')
     def test_resource_type_template(self):
         """Verify it is possible to get template about resource types."""
diff --git a/tempest/api/orchestration/stacks/test_soft_conf.py b/tempest/api/orchestration/stacks/test_soft_conf.py
index dae0bab..8192999 100644
--- a/tempest/api/orchestration/stacks/test_soft_conf.py
+++ b/tempest/api/orchestration/stacks/test_soft_conf.py
@@ -14,7 +14,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class TestSoftwareConfig(base.BaseOrchestrationTest):
@@ -75,7 +74,7 @@
         self.assertRaises(
             lib_exc.NotFound, self.client.show_software_config, config_id)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('136162ed-9445-4b9c-b7fc-306af8b5da99')
     def test_get_software_config(self):
         """Testing software config get."""
@@ -83,7 +82,7 @@
             api_config = self.client.show_software_config(conf['id'])
             self._validate_config(conf, api_config)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('1275c835-c967-4a2c-8d5d-ad533447ed91')
     def test_get_deployment_list(self):
         """Getting a list of all deployments"""
@@ -92,7 +91,7 @@
                       deploy_list['software_deployments']]
         self.assertIn(self.deployment_id, deploy_ids)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('fe7cd9f9-54b1-429c-a3b7-7df8451db913')
     def test_get_deployment_metadata(self):
         """Testing deployment metadata get"""
@@ -110,7 +109,7 @@
         self.assertEqual(config_id,
                          deployment['software_deployment']['config_id'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f29d21f3-ed75-47cf-8cdc-ef1bdeb4c674')
     def test_software_deployment_create_validate(self):
         """Testing software deployment was created as expected."""
@@ -123,7 +122,7 @@
         self._validate_deployment(self.action, self.status,
                                   self.status_reason, self.configs[0]['id'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('2ac43ab3-34f2-415d-be2e-eabb4d14ee32')
     def test_software_deployment_update_no_metadata_change(self):
         """Testing software deployment update without metadata change."""
@@ -149,7 +148,7 @@
                 metadata['metadata'][0][key],
                 test_metadata['metadata'][0][key])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('92c48944-d79d-4595-a840-8e1a581c1a72')
     def test_software_deployment_update_with_metadata_change(self):
         """Testing software deployment update with metadata change."""
diff --git a/tempest/api/orchestration/stacks/test_stacks.py b/tempest/api/orchestration/stacks/test_stacks.py
index 0be135b..dc1bb4f 100644
--- a/tempest/api/orchestration/stacks/test_stacks.py
+++ b/tempest/api/orchestration/stacks/test_stacks.py
@@ -13,19 +13,18 @@
 from tempest.api.orchestration import base
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class StacksTestJSON(base.BaseOrchestrationTest):
     empty_template = "HeatTemplateFormatVersion: '2012-12-12'\n"
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('d35d628c-07f6-4674-85a1-74db9919e986')
     def test_stack_list_responds(self):
         stacks = self.client.list_stacks()['stacks']
         self.assertIsInstance(stacks, list)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('10498bd5-a83e-4b62-a817-ce24afe938fe')
     def test_stack_crud_no_resources(self):
         stack_name = data_utils.rand_name('heat')
diff --git a/tempest/api/orchestration/stacks/test_templates_negative.py b/tempest/api/orchestration/stacks/test_templates_negative.py
index a90abe2..eb93d95 100644
--- a/tempest/api/orchestration/stacks/test_templates_negative.py
+++ b/tempest/api/orchestration/stacks/test_templates_negative.py
@@ -15,7 +15,6 @@
 from tempest.api.orchestration import base
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class TemplateYAMLNegativeTestJSON(base.BaseOrchestrationTest):
@@ -35,7 +34,7 @@
         super(TemplateYAMLNegativeTestJSON, cls).resource_setup()
         cls.parameters = {}
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5586cbca-ddc4-4152-9db8-fa1ce5fc1876')
     def test_validate_template_url(self):
         """Validating template passing url to it."""
diff --git a/tempest/api/volume/admin/test_volume_quotas_negative.py b/tempest/api/volume/admin/test_volume_quotas_negative.py
index 10cf890..63f61e4 100644
--- a/tempest/api/volume/admin/test_volume_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_quotas_negative.py
@@ -17,7 +17,6 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -46,14 +45,14 @@
         # they are created using utility wrapper methods.
         cls.volume = cls.create_volume()
 
-    @test.attr(type='negative')
+    @decorators.attr(type='negative')
     @decorators.idempotent_id('bf544854-d62a-47f2-a681-90f7a47d86b6')
     def test_quota_volumes(self):
         self.assertRaises(lib_exc.OverLimit,
                           self.volumes_client.create_volume,
                           size=CONF.volume.volume_size)
 
-    @test.attr(type='negative')
+    @decorators.attr(type='negative')
     @decorators.idempotent_id('2dc27eee-8659-4298-b900-169d71a91374')
     def test_quota_volume_gigabytes(self):
         # NOTE(gfidente): quota set needs to be changed for this test
diff --git a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
index e5c78cb..fa8c7ab 100644
--- a/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
+++ b/tempest/api/volume/admin/test_volume_snapshot_quotas_negative.py
@@ -17,7 +17,6 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -54,14 +53,14 @@
         cls.volume = cls.create_volume()
         cls.snapshot = cls.create_snapshot(volume_id=cls.volume['id'])
 
-    @test.attr(type='negative')
+    @decorators.attr(type='negative')
     @decorators.idempotent_id('02bbf63f-6c05-4357-9d98-2926a94064ff')
     def test_quota_volume_snapshots(self):
         self.assertRaises(lib_exc.OverLimit,
                           self.snapshots_client.create_snapshot,
                           volume_id=self.volume['id'])
 
-    @test.attr(type='negative')
+    @decorators.attr(type='negative')
     @decorators.idempotent_id('c99a1ca9-6cdf-498d-9fdf-25832babef27')
     def test_quota_volume_gigabytes_snapshots(self):
         self.addCleanup(self.admin_quotas_client.update_quota_set,
diff --git a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
index 4efc44b..4fa934e 100644
--- a/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_extra_specs_negative.py
@@ -17,7 +17,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class ExtraSpecsNegativeTest(base.BaseVolumeAdminTest):
@@ -28,7 +27,7 @@
         extra_specs = {"spec1": "val1"}
         cls.volume_type = cls.create_volume_type(extra_specs=extra_specs)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('08961d20-5cbb-4910-ac0f-89ad6dbb2da1')
     def test_update_no_body(self):
         # Should not update volume type extra specs with no body
@@ -37,7 +36,7 @@
             self.admin_volume_types_client.update_volume_type_extra_specs,
             self.volume_type['id'], "spec1", None)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('25e5a0ee-89b3-4c53-8310-236f76c75365')
     def test_update_nonexistent_extra_spec_id(self):
         # Should not update volume type extra specs with nonexistent id.
@@ -48,7 +47,7 @@
             self.volume_type['id'], data_utils.rand_uuid(),
             extra_spec)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9bf7a657-b011-4aec-866d-81c496fbe5c8')
     def test_update_none_extra_spec_id(self):
         # Should not update volume type extra specs with none id.
@@ -58,7 +57,7 @@
             self.admin_volume_types_client.update_volume_type_extra_specs,
             self.volume_type['id'], None, extra_spec)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('a77dfda2-9100-448e-9076-ed1711f4bdfc')
     def test_update_multiple_extra_spec(self):
         # Should not update volume type extra specs with multiple specs as
@@ -70,7 +69,7 @@
             self.volume_type['id'], list(extra_spec)[0],
             extra_spec)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('49d5472c-a53d-4eab-a4d3-450c4db1c545')
     def test_create_nonexistent_type_id(self):
         # Should not create volume type extra spec for nonexistent volume
@@ -81,7 +80,7 @@
             self.admin_volume_types_client.create_volume_type_extra_specs,
             data_utils.rand_uuid(), extra_specs)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c821bdc8-43a4-4bf4-86c8-82f3858d5f7d')
     def test_create_none_body(self):
         # Should not create volume type extra spec for none POST body.
@@ -90,7 +89,7 @@
             self.admin_volume_types_client.create_volume_type_extra_specs,
             self.volume_type['id'], None)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bc772c71-1ed4-4716-b945-8b5ed0f15e87')
     def test_create_invalid_body(self):
         # Should not create volume type extra spec for invalid POST body.
@@ -99,7 +98,7 @@
             self.admin_volume_types_client.create_volume_type_extra_specs,
             self.volume_type['id'], extra_specs=['invalid'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('031cda8b-7d23-4246-8bf6-bbe73fd67074')
     def test_delete_nonexistent_volume_type_id(self):
         # Should not delete volume type extra spec for nonexistent
@@ -109,7 +108,7 @@
             self.admin_volume_types_client.delete_volume_type_extra_specs,
             data_utils.rand_uuid(), "spec1")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('dee5cf0c-cdd6-4353-b70c-e847050d71fb')
     def test_list_nonexistent_volume_type_id(self):
         # Should not list volume type extra spec for nonexistent type id.
@@ -118,7 +117,7 @@
             self.admin_volume_types_client.list_volume_types_extra_specs,
             data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9f402cbd-1838-4eb4-9554-126a6b1908c9')
     def test_get_nonexistent_volume_type_id(self):
         # Should not get volume type extra spec for nonexistent type id.
@@ -127,7 +126,7 @@
             self.admin_volume_types_client.show_volume_type_extra_specs,
             data_utils.rand_uuid(), "spec1")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c881797d-12ff-4f1a-b09d-9f6212159753')
     def test_get_nonexistent_extra_spec_id(self):
         # Should not get volume type extra spec for nonexistent extra spec
diff --git a/tempest/api/volume/admin/test_volume_types_negative.py b/tempest/api/volume/admin/test_volume_types_negative.py
index bac2ea3..4cad52a 100644
--- a/tempest/api/volume/admin/test_volume_types_negative.py
+++ b/tempest/api/volume/admin/test_volume_types_negative.py
@@ -17,12 +17,11 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 
 class VolumeTypesNegativeTest(base.BaseVolumeAdminTest):
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b48c98f2-e662-4885-9b71-032256906314')
     def test_create_with_nonexistent_volume_type(self):
         # Should not be able to create volume with nonexistent volume_type.
@@ -31,7 +30,7 @@
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.create_volume, **params)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('878b4e57-faa2-4659-b0d1-ce740a06ae81')
     def test_create_with_empty_name(self):
         # Should not be able to create volume type with an empty name.
@@ -39,7 +38,7 @@
             lib_exc.BadRequest,
             self.admin_volume_types_client.create_volume_type, name='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('994610d6-0476-4018-a644-a2602ef5d4aa')
     def test_get_nonexistent_type_id(self):
         # Should not be able to get volume type with nonexistent type id.
@@ -47,7 +46,7 @@
                           self.admin_volume_types_client.show_volume_type,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('6b3926d2-7d73-4896-bc3d-e42dfd11a9f6')
     def test_delete_nonexistent_type_id(self):
         # Should not be able to delete volume type with nonexistent type id.
@@ -55,7 +54,7 @@
                           self.admin_volume_types_client.delete_volume_type,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8c09f849-f225-4d78-ba87-bffd9a5e0c6f')
     def test_create_volume_with_private_volume_type(self):
         # Should not be able to create volume with private volume type.
diff --git a/tempest/api/volume/test_versions.py b/tempest/api/volume/test_versions.py
index 76f2a99..0083a3b 100644
--- a/tempest/api/volume/test_versions.py
+++ b/tempest/api/volume/test_versions.py
@@ -14,7 +14,6 @@
 
 from tempest.api.volume import base
 from tempest.lib import decorators
-from tempest import test
 
 
 class VersionsTest(base.BaseVolumeTest):
@@ -22,7 +21,7 @@
     _api_version = 3
 
     @decorators.idempotent_id('77838fc4-b49b-4c64-9533-166762517369')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     def test_list_versions(self):
         # NOTE: The version data is checked on service client side
         #       with JSON-Schema validation. It is enough to just call
diff --git a/tempest/api/volume/test_volumes_actions.py b/tempest/api/volume/test_volumes_actions.py
index a2a3d27..1e05f22 100644
--- a/tempest/api/volume/test_volumes_actions.py
+++ b/tempest/api/volume/test_volumes_actions.py
@@ -49,7 +49,7 @@
         cls.volume = cls.create_volume()
 
     @decorators.idempotent_id('fff42874-7db5-4487-a8e1-ddda5fb5288d')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @test.services('compute')
     def test_attach_detach_volume_to_instance(self):
         # Create a server
diff --git a/tempest/api/volume/test_volumes_clone_negative.py b/tempest/api/volume/test_volumes_clone_negative.py
index 9169c19..bba7a0b 100644
--- a/tempest/api/volume/test_volumes_clone_negative.py
+++ b/tempest/api/volume/test_volumes_clone_negative.py
@@ -17,7 +17,6 @@
 from tempest import config
 from tempest.lib import decorators
 from tempest.lib import exceptions
-from tempest import test
 
 CONF = config.CONF
 
@@ -30,7 +29,7 @@
         if not CONF.volume_feature_enabled.clone:
             raise cls.skipException("Cinder volume clones are disabled")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9adae371-a257-43a5-459a-dc7c88e66e0e')
     def test_create_from_volume_decreasing_size(self):
         # Creates a volume from another volume passing a size different from
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 65027bf..1d9b846 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -115,12 +115,12 @@
         else:
             self.assertEqual('false', updated_volume['bootable'])
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('27fb0e9f-fb64-41dd-8bdb-1ffa762f0d51')
     def test_volume_create_get_update_delete(self):
         self._volume_create_get_update_delete(size=CONF.volume.volume_size)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('54a01030-c7fc-447c-86ee-c1182beae638')
     @test.services('image')
     def test_volume_create_get_update_delete_from_image(self):
diff --git a/tempest/api/volume/test_volumes_list.py b/tempest/api/volume/test_volumes_list.py
index 6b9f131..ea9ddca 100644
--- a/tempest/api/volume/test_volumes_list.py
+++ b/tempest/api/volume/test_volumes_list.py
@@ -23,7 +23,6 @@
 from tempest.api.volume import base
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
-from tempest import test
 
 
 class VolumesListTestJSON(base.BaseVolumeTest):
@@ -99,7 +98,7 @@
                     else:
                         self.assertEqual(params[key], volume[key], msg)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('0b6ddd39-b948-471f-8038-4787978747c4')
     def test_volume_list(self):
         # Get a list of Volumes
diff --git a/tempest/api/volume/test_volumes_negative.py b/tempest/api/volume/test_volumes_negative.py
index 609a031..5ba72c3 100644
--- a/tempest/api/volume/test_volumes_negative.py
+++ b/tempest/api/volume/test_volumes_negative.py
@@ -30,28 +30,28 @@
         cls.volume = cls.create_volume()
         cls.mountpoint = "/dev/vdc"
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f131c586-9448-44a4-a8b0-54ca838aa43e')
     def test_volume_get_nonexistent_volume_id(self):
         # Should not be able to get a non-existent volume
         self.assertRaises(lib_exc.NotFound, self.volumes_client.show_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('555efa6e-efcd-44ef-8a3b-4a7ca4837a29')
     def test_volume_delete_nonexistent_volume_id(self):
         # Should not be able to delete a non-existent Volume
         self.assertRaises(lib_exc.NotFound, self.volumes_client.delete_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1ed83a8a-682d-4dfb-a30e-ee63ffd6c049')
     def test_create_volume_with_invalid_size(self):
         # Should not be able to create volume with invalid size in request
         self.assertRaises(lib_exc.BadRequest,
                           self.volumes_client.create_volume, size='#$%')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9387686f-334f-4d31-a439-33494b9e2683')
     def test_create_volume_without_passing_size(self):
         # Should not be able to create volume without passing size
@@ -59,88 +59,88 @@
         self.assertRaises(lib_exc.BadRequest,
                           self.volumes_client.create_volume, size='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('41331caa-eaf4-4001-869d-bc18c1869360')
     def test_create_volume_with_size_zero(self):
         # Should not be able to create volume with size zero
         self.assertRaises(lib_exc.BadRequest,
                           self.volumes_client.create_volume, size='0')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8b472729-9eba-446e-a83b-916bdb34bef7')
     def test_create_volume_with_size_negative(self):
         # Should not be able to create volume with size negative
         self.assertRaises(lib_exc.BadRequest,
                           self.volumes_client.create_volume, size='-1')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('10254ed8-3849-454e-862e-3ab8e6aa01d2')
     def test_create_volume_with_nonexistent_volume_type(self):
         # Should not be able to create volume with non-existent volume type
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
                           size='1', volume_type=data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0c36f6ae-4604-4017-b0a9-34fdc63096f9')
     def test_create_volume_with_nonexistent_snapshot_id(self):
         # Should not be able to create volume with non-existent snapshot
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
                           size='1', snapshot_id=data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('47c73e08-4be8-45bb-bfdf-0c4e79b88344')
     def test_create_volume_with_nonexistent_source_volid(self):
         # Should not be able to create volume with non-existent source volume
         self.assertRaises(lib_exc.NotFound, self.volumes_client.create_volume,
                           size='1', source_volid=data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0186422c-999a-480e-a026-6a665744c30c')
     def test_update_volume_with_nonexistent_volume_id(self):
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
                           volume_id=data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e66e40d6-65e6-4e75-bdc7-636792fa152d')
     def test_update_volume_with_invalid_volume_id(self):
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
                           volume_id=data_utils.rand_name('invalid'))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('72aeca85-57a5-4c1f-9057-f320f9ea575b')
     def test_update_volume_with_empty_volume_id(self):
         self.assertRaises(lib_exc.NotFound, self.volumes_client.update_volume,
                           volume_id='')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('30799cfd-7ee4-446c-b66c-45b383ed211b')
     def test_get_invalid_volume_id(self):
         # Should not be able to get volume with invalid id
         self.assertRaises(lib_exc.NotFound, self.volumes_client.show_volume,
                           data_utils.rand_name('invalid'))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('c6c3db06-29ad-4e91-beb0-2ab195fe49e3')
     def test_get_volume_without_passing_volume_id(self):
         # Should not be able to get volume when empty ID is passed
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.show_volume, '')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('1f035827-7c32-4019-9240-b4ec2dbd9dfd')
     def test_delete_invalid_volume_id(self):
         # Should not be able to delete volume when invalid ID is passed
         self.assertRaises(lib_exc.NotFound, self.volumes_client.delete_volume,
                           data_utils.rand_name('invalid'))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('441a1550-5d44-4b30-af0f-a6d402f52026')
     def test_delete_volume_without_passing_volume_id(self):
         # Should not be able to delete volume when empty ID is passed
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.delete_volume, '')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('f5e56b0a-5d02-43c1-a2a7-c9b792c2e3f6')
     @test.services('compute')
     def test_attach_volumes_with_nonexistent_volume_id(self):
@@ -152,14 +152,14 @@
                           instance_uuid=server['id'],
                           mountpoint=self.mountpoint)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9f9c24e4-011d-46b5-b992-952140ce237a')
     def test_detach_volumes_with_invalid_volume_id(self):
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.detach_volume,
                           'xxx')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e0c75c74-ee34-41a9-9288-2a2051452854')
     def test_volume_extend_with_size_smaller_than_original_size(self):
         # Extend volume with smaller size than original size.
@@ -168,7 +168,7 @@
                           self.volumes_client.extend_volume,
                           self.volume['id'], new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('5d0b480d-e833-439f-8a5a-96ad2ed6f22f')
     def test_volume_extend_with_non_number_size(self):
         # Extend volume when size is non number.
@@ -177,7 +177,7 @@
                           self.volumes_client.extend_volume,
                           self.volume['id'], new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('355218f1-8991-400a-a6bb-971239287d92')
     def test_volume_extend_with_None_size(self):
         # Extend volume with None size.
@@ -186,7 +186,7 @@
                           self.volumes_client.extend_volume,
                           self.volume['id'], new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8f05a943-013c-4063-ac71-7baf561e82eb')
     def test_volume_extend_with_nonexistent_volume_id(self):
         # Extend volume size when volume is nonexistent.
@@ -194,7 +194,7 @@
         self.assertRaises(lib_exc.NotFound, self.volumes_client.extend_volume,
                           data_utils.rand_uuid(), new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('aff8ba64-6d6f-4f2e-bc33-41a08ee9f115')
     def test_volume_extend_without_passing_volume_id(self):
         # Extend volume size when passing volume id is None.
@@ -202,21 +202,21 @@
         self.assertRaises(lib_exc.NotFound, self.volumes_client.extend_volume,
                           None, new_size=extend_size)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ac6084c0-0546-45f9-b284-38a367e0e0e2')
     def test_reserve_volume_with_nonexistent_volume_id(self):
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.reserve_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('eb467654-3dc1-4a72-9b46-47c29d22654c')
     def test_unreserve_volume_with_nonexistent_volume_id(self):
         self.assertRaises(lib_exc.NotFound,
                           self.volumes_client.unreserve_volume,
                           data_utils.rand_uuid())
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('449c4ed2-ecdd-47bb-98dc-072aeccf158c')
     def test_reserve_volume_with_negative_volume_status(self):
         # Mark volume as reserved.
@@ -228,7 +228,7 @@
         # Unmark volume as reserved.
         self.volumes_client.unreserve_volume(self.volume['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('0f4aa809-8c7b-418f-8fb3-84c7a5dfc52f')
     def test_list_volumes_with_nonexistent_name(self):
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
@@ -237,7 +237,7 @@
             params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('9ca17820-a0e7-4cbd-a7fa-f4468735e359')
     def test_list_volumes_detail_with_nonexistent_name(self):
         v_name = data_utils.rand_name(self.__class__.__name__ + '-Volume')
@@ -247,7 +247,7 @@
                 detail=True, params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('143b279b-7522-466b-81be-34a87d564a7c')
     def test_list_volumes_with_invalid_status(self):
         params = {'status': 'null'}
@@ -255,7 +255,7 @@
             params=params)['volumes']
         self.assertEqual(0, len(fetched_volume))
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('ba94b27b-be3f-496c-a00e-0283b373fa75')
     def test_list_volumes_detail_with_invalid_status(self):
         params = {'status': 'null'}
diff --git a/tempest/api/volume/test_volumes_snapshots_negative.py b/tempest/api/volume/test_volumes_snapshots_negative.py
index 2e30d04..ea5f036 100644
--- a/tempest/api/volume/test_volumes_snapshots_negative.py
+++ b/tempest/api/volume/test_volumes_snapshots_negative.py
@@ -15,7 +15,6 @@
 from tempest.lib.common.utils import data_utils
 from tempest.lib import decorators
 from tempest.lib import exceptions as lib_exc
-from tempest import test
 
 CONF = config.CONF
 
@@ -28,7 +27,7 @@
         if not CONF.volume_feature_enabled.snapshot:
             raise cls.skipException("Cinder volume snapshots are disabled")
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('e3e466af-70ab-4f4b-a967-ab04e3532ea7')
     def test_create_snapshot_with_nonexistent_volume_id(self):
         # Create a snapshot with nonexistent volume id
@@ -38,7 +37,7 @@
                           volume_id=data_utils.rand_uuid(),
                           display_name=s_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('bb9da53e-d335-4309-9c15-7e76fd5e4d6d')
     def test_create_snapshot_without_passing_volume_id(self):
         # Create a snapshot without passing volume id
@@ -47,7 +46,7 @@
                           self.snapshots_client.create_snapshot,
                           volume_id=None, display_name=s_name)
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('677863d1-34f9-456d-b6ac-9924f667a7f4')
     def test_volume_from_snapshot_decreasing_size(self):
         # Creates a volume a snapshot passing a size different from the source
@@ -62,21 +61,21 @@
                           size=src_size - 1,
                           snapshot_id=src_snap['id'])
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('8fd92339-e22f-4591-86b4-1e2215372a40')
     def test_list_snapshot_invalid_param_limit(self):
         self.assertRaises(lib_exc.BadRequest,
                           self.snapshots_client.list_snapshots,
                           limit='invalid')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('27b5f37f-bf69-4e8c-986e-c44f3d6819b8')
     def test_list_snapshots_invalid_param_sort(self):
         self.assertRaises(lib_exc.BadRequest,
                           self.snapshots_client.list_snapshots,
                           sort_key='invalid')
 
-    @test.attr(type=['negative'])
+    @decorators.attr(type=['negative'])
     @decorators.idempotent_id('b68deeda-ca79-4a32-81af-5c51179e553a')
     def test_list_snapshots_invalid_param_marker(self):
         self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/lib/decorators.py b/tempest/lib/decorators.py
index c2ee212..f82f707 100644
--- a/tempest/lib/decorators.py
+++ b/tempest/lib/decorators.py
@@ -104,3 +104,21 @@
                 raise testtools.TestCase.skipException(self.message)
             func(*args, **kw)
         return _skipper
+
+
+def attr(**kwargs):
+    """A decorator which applies the testtools attr decorator
+
+    This decorator applies the testtools.testcase.attr if it is in the list of
+    attributes to testtools we want to apply.
+    """
+
+    def decorator(f):
+        if 'type' in kwargs and isinstance(kwargs['type'], str):
+            f = testtools.testcase.attr(kwargs['type'])(f)
+        elif 'type' in kwargs and isinstance(kwargs['type'], list):
+            for attr in kwargs['type']:
+                f = testtools.testcase.attr(attr)(f)
+        return f
+
+    return decorator
diff --git a/tempest/scenario/test_aggregates_basic_ops.py b/tempest/scenario/test_aggregates_basic_ops.py
index cefa119..8408a1e 100644
--- a/tempest/scenario/test_aggregates_basic_ops.py
+++ b/tempest/scenario/test_aggregates_basic_ops.py
@@ -96,7 +96,7 @@
         return aggregate
 
     @decorators.idempotent_id('cb2b4c4f-0c7c-4164-bdde-6285b302a081')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute')
     def test_aggregate_basic_ops(self):
         self.useFixture(fixtures.LockFixture('availability_zone'))
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index a05b1b1..d7b86f6 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -62,7 +62,7 @@
         self.nova_volume_detach(server, attached_volume)
 
     @decorators.idempotent_id('79165fb4-5534-4b9d-8429-97ccffb8f86e')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'volume', 'image')
     def test_encrypted_cinder_volumes_luks(self):
         server = self.launch_instance()
@@ -72,7 +72,7 @@
         self.attach_detach_volume(server, volume)
 
     @decorators.idempotent_id('cbc752ed-b716-4717-910f-956cce965722')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'volume', 'image')
     def test_encrypted_cinder_volumes_cryptsetup(self):
         server = self.launch_instance()
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index 6665fa7..ae2ba2f 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -104,7 +104,7 @@
         return body['OS-EXT-SRV-ATTR:host']
 
     @decorators.idempotent_id('61f1aa9a-1573-410e-9054-afa557cab021')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_stop_start(self):
         keypair = self.create_keypair()
@@ -130,7 +130,7 @@
             server, keypair, floating_ip)
 
     @decorators.idempotent_id('88a529c2-1daa-4c85-9aec-d541ba3eb699')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_rebuild(self):
         keypair = self.create_keypair()
@@ -145,7 +145,7 @@
     @decorators.idempotent_id('2b2642db-6568-4b35-b812-eceed3fa20ce')
     @testtools.skipUnless(CONF.compute_feature_enabled.pause,
                           'Pause is not available.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_pause_unpause(self):
         keypair = self.create_keypair()
@@ -163,7 +163,7 @@
     @decorators.idempotent_id('5cdf9499-541d-4923-804e-b9a60620a7f0')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_suspend_resume(self):
         keypair = self.create_keypair()
@@ -181,7 +181,7 @@
     @decorators.idempotent_id('719eb59d-2f42-4b66-b8b1-bb1254473967')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize is not available.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_resize(self):
         resize_flavor = CONF.compute.flavor_ref_alt
@@ -205,7 +205,7 @@
     @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
                           'Less than 2 compute nodes, skipping multinode '
                           'tests.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_cold_migration(self):
         keypair = self.create_keypair()
@@ -231,7 +231,7 @@
     @testtools.skipUnless(CONF.compute.min_compute_nodes > 1,
                           'Less than 2 compute nodes, skipping multinode '
                           'tests.')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_server_connectivity_cold_migration_revert(self):
         keypair = self.create_keypair()
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index dec0ad0..756ca4d 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -352,7 +352,7 @@
             self.check_remote_connectivity(ssh_source, remote_ip,
                                            should_connect)
 
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @decorators.idempotent_id('f323b3ba-82f8-4db7-8ea6-6a895869ec49')
     @test.services('compute', 'network')
     def test_network_basic_ops(self):
@@ -408,7 +408,7 @@
     @decorators.idempotent_id('b158ea55-472e-4086-8fa9-c64ac0c6c1d0')
     @testtools.skipUnless(test.is_extension_enabled('net-mtu', 'network'),
                           'No way to calculate MTU for networks')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_mtu_sized_frames(self):
         """Validate that network MTU sized frames fit through."""
@@ -421,7 +421,7 @@
                       'Connectivity can only be tested when in a '
                       'multitenant network environment')
     @decorators.skip_because(bug="1610994")
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_connectivity_between_vms_on_different_networks(self):
         """Test connectivity between VMs on different networks
@@ -497,7 +497,7 @@
     @testtools.skipIf(CONF.network.shared_physical_network,
                       'Router state can be altered only with multitenant '
                       'networks capabilities')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_update_router_admin_state(self):
         """Test to update admin state up of router
@@ -531,7 +531,7 @@
                       'network isolation not available')
     @testtools.skipUnless(CONF.scenario.dhcp_client,
                           "DHCP client is not available.")
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_subnet_details(self):
         """Tests that subnet's extra configuration details are affecting VMs.
@@ -615,7 +615,7 @@
     @testtools.skipUnless(CONF.network_feature_enabled.port_admin_state_change,
                           "Changing a port's admin state is not supported "
                           "by the test environment")
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_update_instance_port_admin_state(self):
         """Test to update admin_state_up attribute of instance port
@@ -661,7 +661,7 @@
                                        should_succeed=True)
 
     @decorators.idempotent_id('759462e1-8535-46b0-ab3a-33aa45c55aaa')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_preserve_preexisting_port(self):
         """Test preserve pre-existing port
@@ -713,7 +713,7 @@
 
     @test.requires_ext(service='network', extension='l3_agent_scheduler')
     @decorators.idempotent_id('2e788c46-fb3f-4ac9-8f82-0561555bea73')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_router_rescheduling(self):
         """Tests that router can be removed from agent and add to a new agent.
@@ -793,7 +793,7 @@
     @testtools.skipUnless(CONF.compute_feature_enabled.interface_attach,
                           'NIC hotplug not available')
     @decorators.idempotent_id('7c0bb1a2-d053-49a4-98f9-ca1a1d849f63')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_port_security_macspoofing_port(self):
         """Tests port_security extension enforces mac spoofing
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 4e8b004..daf4d13 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -206,43 +206,43 @@
             self.check_remote_connectivity(sshv4_2,
                                            self.subnets_v6[i]['gateway_ip'])
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('2c92df61-29f0-4eaa-bee3-7c65bef62a43')
     @test.services('compute', 'network')
     def test_slaac_from_os(self):
         self._prepare_and_test(address6_mode='slaac')
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('d7e1f858-187c-45a6-89c9-bdafde619a9f')
     @test.services('compute', 'network')
     def test_dhcp6_stateless_from_os(self):
         self._prepare_and_test(address6_mode='dhcpv6-stateless')
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('7ab23f41-833b-4a16-a7c9-5b42fe6d4123')
     @test.services('compute', 'network')
     def test_multi_prefix_dhcpv6_stateless(self):
         self._prepare_and_test(address6_mode='dhcpv6-stateless', n_subnets6=2)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('dec222b1-180c-4098-b8c5-cc1b8342d611')
     @test.services('compute', 'network')
     def test_multi_prefix_slaac(self):
         self._prepare_and_test(address6_mode='slaac', n_subnets6=2)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('b6399d76-4438-4658-bcf5-0d6c8584fde2')
     @test.services('compute', 'network')
     def test_dualnet_slaac_from_os(self):
         self._prepare_and_test(address6_mode='slaac', dualnet=True)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('76f26acd-9688-42b4-bc3e-cd134c4cb09e')
     @test.services('compute', 'network')
     def test_dualnet_dhcp6_stateless_from_os(self):
         self._prepare_and_test(address6_mode='dhcpv6-stateless', dualnet=True)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('cf1c4425-766b-45b8-be35-e2959728eb00')
     @test.services('compute', 'network')
     def test_dualnet_multi_prefix_dhcpv6_stateless(self):
diff --git a/tempest/scenario/test_object_storage_basic_ops.py b/tempest/scenario/test_object_storage_basic_ops.py
index 7fd8c91..25e9f5c 100644
--- a/tempest/scenario/test_object_storage_basic_ops.py
+++ b/tempest/scenario/test_object_storage_basic_ops.py
@@ -46,7 +46,7 @@
         self.delete_container(container_name)
 
     @decorators.idempotent_id('916c7111-cb1f-44b2-816d-8f760e4ea910')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('object_storage')
     def test_swift_acl_anonymous_download(self):
         """This test will cover below steps:
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 55a3db8..e777a34 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -494,7 +494,7 @@
             raise
 
     @decorators.idempotent_id('f4d556d7-1526-42ad-bafb-6bebf48568f6')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_port_update_new_security_group(self):
         """Verifies the traffic after updating the vm port
@@ -549,7 +549,7 @@
             raise
 
     @decorators.idempotent_id('d2f77418-fcc4-439d-b935-72eca704e293')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'network')
     def test_multiple_security_groups(self):
         """Verify multiple security groups and checks that rules
@@ -581,7 +581,7 @@
                                    private_key=private_key,
                                    should_connect=True)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.requires_ext(service='network', extension='port-security')
     @decorators.idempotent_id('7c811dcc-263b-49a3-92d2-1b4d8405f50c')
     @test.services('compute', 'network')
@@ -622,7 +622,7 @@
                 self._log_console_output(servers=tenant.servers)
             raise
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.requires_ext(service='network', extension='port-security')
     @decorators.idempotent_id('13ccf253-e5ad-424b-9c4a-97b88a026699')
     # TODO(mriedem): We shouldn't actually need to check this since neutron
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index cc3687f..6005e28 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -41,7 +41,7 @@
         cls.set_network_resources()
         super(TestServerAdvancedOps, cls).setup_credentials()
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b')
     @testtools.skipUnless(CONF.compute_feature_enabled.resize,
                           'Resize is not available.')
@@ -68,7 +68,7 @@
         waiters.wait_for_server_status(self.servers_client, instance_id,
                                        'ACTIVE')
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('949da7d5-72c8-4808-8802-e3d70df98e2c')
     @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
                           'Suspend is not available.')
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index ddbaf5a..2be9e06 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -124,7 +124,7 @@
             # instance info and do direct comparison.
 
     @decorators.idempotent_id('7fff3fb3-91d8-4fd0-bd7d-0204f1f180ba')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @test.services('compute', 'network')
     def test_server_basic_ops(self):
         keypair = self.create_keypair()
diff --git a/tempest/scenario/test_server_multinode.py b/tempest/scenario/test_server_multinode.py
index db91a21..bf2858b 100644
--- a/tempest/scenario/test_server_multinode.py
+++ b/tempest/scenario/test_server_multinode.py
@@ -45,7 +45,7 @@
         cls.servers_client = cls.admin_manager.servers_client
 
     @decorators.idempotent_id('9cecbe35-b9d4-48da-a37e-7ce70aa43d30')
-    @test.attr(type='smoke')
+    @decorators.attr(type='smoke')
     @test.services('compute', 'network')
     def test_schedule_to_all_nodes(self):
         available_zone = \
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index 9e763f8..fc04b44 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -74,7 +74,7 @@
                                         private_key=keypair['private_key'])
         self.assertEqual(timestamp, timestamp2)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('1164e700-0af0-4a4c-8792-35909a88743c')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
@@ -82,7 +82,7 @@
     def test_shelve_instance(self):
         self._create_server_then_shelve_and_unshelve()
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('c1b6318c-b9da-490b-9c67-9339b627271f')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index a699de2..52767dc 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -41,7 +41,7 @@
             raise cls.skipException("Snapshotting is not available.")
 
     @decorators.idempotent_id('608e604b-1d63-4a82-8e3e-91bc665c90b4')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @testtools.skipUnless(CONF.network.public_network_id,
                           'The public_network_id option must be specified.')
     @test.services('compute', 'network', 'image')
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 5f5d701..debd664 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -85,7 +85,7 @@
                                           CONF.compute.build_interval):
             raise lib_exc.TimeoutException
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.skip_because(bug="1664793")
     @decorators.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
     @testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 888bff2..3dfbf18 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -170,7 +170,7 @@
         self.assertEqual(timestamp, timestamp3)
 
     @decorators.idempotent_id('05795fb2-b2a7-4c9f-8fac-ff25aedb1489')
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @test.services('compute', 'image', 'volume')
     def test_create_server_from_volume_snapshot(self):
         # Create a volume from an image
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
index f04947c..a3cb3eb 100644
--- a/tempest/scenario/test_volume_migrate_attached.py
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -88,7 +88,7 @@
         waiters.wait_for_volume_retype(self.volumes_client,
                                        volume_id, new_volume_type)
 
-    @test.attr(type='slow')
+    @decorators.attr(type='slow')
     @decorators.idempotent_id('deadd2c2-beef-4dce-98be-f86765ff311b')
     @test.services('compute', 'volume')
     def test_volume_migrate_attached(self):
diff --git a/tempest/test.py b/tempest/test.py
index 052033d..8b015cd 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -50,22 +50,9 @@
     version='Pike', removal_version='?')
 
 
-def attr(**kwargs):
-    """A decorator which applies the testtools attr decorator
-
-    This decorator applies the testtools.testcase.attr if it is in the list of
-    attributes to testtools we want to apply.
-    """
-
-    def decorator(f):
-        if 'type' in kwargs and isinstance(kwargs['type'], str):
-            f = testtools.testcase.attr(kwargs['type'])(f)
-        elif 'type' in kwargs and isinstance(kwargs['type'], list):
-            for attr in kwargs['type']:
-                f = testtools.testcase.attr(attr)(f)
-        return f
-
-    return decorator
+attr = debtcollector.moves.moved_function(
+    decorators.attr, 'attr', __name__,
+    version='Pike', removal_version='?')
 
 
 def get_service_list():
@@ -93,7 +80,7 @@
             if service not in known_services:
                 raise exceptions.InvalidServiceTag('%s is not a valid '
                                                    'service' % service)
-        attr(type=list(args))(f)
+        decorators.attr(type=list(args))(f)
 
         @functools.wraps(f)
         def wrapper(self, *func_args, **func_kwargs):
diff --git a/tempest/tests/lib/test_decorators.py b/tempest/tests/lib/test_decorators.py
index ea38e08..bbebcd3 100644
--- a/tempest/tests/lib/test_decorators.py
+++ b/tempest/tests/lib/test_decorators.py
@@ -22,6 +22,34 @@
 from tempest.tests import base
 
 
+class TestAttrDecorator(base.TestCase):
+    def _test_attr_helper(self, expected_attrs, **decorator_args):
+        @decorators.attr(**decorator_args)
+        def foo():
+            pass
+
+        # By our decorators.attr decorator the attribute __testtools_attrs
+        # will be set only for 'type' argument, so we test it first.
+        if 'type' in decorator_args:
+            # this is what testtools sets
+            self.assertEqual(getattr(foo, '__testtools_attrs'),
+                             set(expected_attrs))
+
+    def test_attr_without_type(self):
+        self._test_attr_helper(expected_attrs='baz', bar='baz')
+
+    def test_attr_decorator_with_list_type(self):
+        # if type is 'smoke' we'll get the original list of types
+        self._test_attr_helper(expected_attrs=['smoke', 'foo'],
+                               type=['smoke', 'foo'])
+
+    def test_attr_decorator_with_unknown_type(self):
+        self._test_attr_helper(expected_attrs=['foo'], type='foo')
+
+    def test_attr_decorator_with_duplicated_type(self):
+        self._test_attr_helper(expected_attrs=['foo'], type=['foo', 'foo'])
+
+
 class TestSkipBecauseDecorator(base.TestCase):
     def _test_skip_because_helper(self, expected_to_skip=True,
                                   **decorator_args):
diff --git a/tempest/tests/test_decorators.py b/tempest/tests/test_decorators.py
index ae2f2a3..149a54c 100644
--- a/tempest/tests/test_decorators.py
+++ b/tempest/tests/test_decorators.py
@@ -32,34 +32,6 @@
                          fake_config.FakePrivate)
 
 
-class TestAttrDecorator(BaseDecoratorsTest):
-    def _test_attr_helper(self, expected_attrs, **decorator_args):
-        @test.attr(**decorator_args)
-        def foo():
-            pass
-
-        # By our test.attr decorator the attribute __testtools_attrs will be
-        # set only for 'type' argument, so we test it first.
-        if 'type' in decorator_args:
-            # this is what testtools sets
-            self.assertEqual(getattr(foo, '__testtools_attrs'),
-                             set(expected_attrs))
-
-    def test_attr_without_type(self):
-        self._test_attr_helper(expected_attrs='baz', bar='baz')
-
-    def test_attr_decorator_with_list_type(self):
-        # if type is 'smoke' we'll get the original list of types
-        self._test_attr_helper(expected_attrs=['smoke', 'foo'],
-                               type=['smoke', 'foo'])
-
-    def test_attr_decorator_with_unknown_type(self):
-        self._test_attr_helper(expected_attrs=['foo'], type='foo')
-
-    def test_attr_decorator_with_duplicated_type(self):
-        self._test_attr_helper(expected_attrs=['foo'], type=['foo', 'foo'])
-
-
 class TestIdempotentIdDecorator(BaseDecoratorsTest):
 
     def _test_helper(self, _id, **decorator_args):