1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15- import unittest
16-
17- import bookshelf
18- import config
15+ from conftest import flaky_filter
1916from flaky import flaky
20- from gcloud .exceptions import ServiceUnavailable
21- from nose .plugins .attrib import attr
22-
23-
24- def flaky_filter (e , * args ):
25- return isinstance (e , ServiceUnavailable )
17+ import pytest
2618
2719
20+ # Mark all test cases in this class as flaky, so that if errors occur they
21+ # can be retried. This is useful when databases are temporarily unavailable.
2822@flaky (rerun_filter = flaky_filter )
29- class IntegrationBase (unittest .TestCase ):
30-
31- def createBooks (self , n = 1 ):
32- with self .app .test_request_context ():
33- for i in range (1 , n + 1 ):
34- self .model .create ({'title' : u'Book {0}' .format (i )})
35-
36- def setUp (self ):
37- self .app = bookshelf .create_app (
38- config ,
39- testing = True ,
40- config_overrides = {
41- 'DATA_BACKEND' : self .backend
42- }
43- )
44-
45- with self .app .app_context ():
46- self .model = bookshelf .get_model ()
47-
48- self .ids_to_delete = []
49-
50- # Monkey-patch create so we can track the IDs of every item
51- # created and delete them during tearDown.
52- self .original_create = self .model .create
53-
54- def tracking_create (* args , ** kwargs ):
55- res = self .original_create (* args , ** kwargs )
56- self .ids_to_delete .append (res ['id' ])
57- return res
58-
59- self .model .create = tracking_create
60-
61- def tearDown (self ):
62-
63- # Delete all items that we created during tests.
64- with self .app .test_request_context ():
65- list (map (self .model .delete , self .ids_to_delete ))
66-
67- self .model .create = self .original_create
68-
69-
70- @attr ('slow' )
71- class CrudTestsMixin (object ):
72- def testList (self ):
73- self .createBooks (11 )
74-
75- with self .app .test_client () as c :
23+ # Tell pytest to use both the app and model fixtures for all test cases.
24+ # This ensures that configuration is properly applied and that all database
25+ # resources created during tests are cleaned up. These fixtures are defined
26+ # in conftest.py
27+ @pytest .mark .usefixtures ('app' , 'model' )
28+ class TestCrudActions (object ):
29+
30+ def test_list (self , app , model ):
31+ for i in range (1 , 12 ):
32+ model .create ({'title' : u'Book {0}' .format (i )})
33+
34+ with app .test_client () as c :
7635 rv = c .get ('/books/' )
7736
7837 assert rv .status == '200 OK'
@@ -84,66 +43,45 @@ def testList(self):
8443 assert 'Book 9' not in body , "Should not show more than 10 books"
8544 assert 'More' in body , "Should have more than one page"
8645
87- def testAddAndView (self ):
46+ def test_add (self , app ):
8847 data = {
8948 'title' : 'Test Book' ,
9049 'author' : 'Test Author' ,
9150 'publishedDate' : 'Test Date Published' ,
9251 'description' : 'Test Description'
9352 }
9453
95- with self . app .test_client () as c :
54+ with app .test_client () as c :
9655 rv = c .post ('/books/add' , data = data , follow_redirects = True )
9756
9857 assert rv .status == '200 OK'
99-
10058 body = rv .data .decode ('utf-8' )
10159 assert 'Test Book' in body
10260 assert 'Test Author' in body
10361 assert 'Test Date Published' in body
10462 assert 'Test Description' in body
10563
106- def testEditAndView (self ):
107- with self .app .test_request_context ():
108- existing = self .model .create ({'title' : "Temp Title" })
64+ def test_edit (self , app , model ):
65+ existing = model .create ({'title' : "Temp Title" })
10966
110- with self . app .test_client () as c :
67+ with app .test_client () as c :
11168 rv = c .post (
11269 '/books/%s/edit' % existing ['id' ],
11370 data = {'title' : 'Updated Title' },
11471 follow_redirects = True )
11572
11673 assert rv .status == '200 OK'
117-
11874 body = rv .data .decode ('utf-8' )
11975 assert 'Updated Title' in body
12076 assert 'Temp Title' not in body
12177
122- def testDelete (self ):
123- with self .app .test_request_context ():
124- existing = self .model .create ({'title' : "Temp Title" })
78+ def test_delete (self , app , model ):
79+ existing = model .create ({'title' : "Temp Title" })
12580
126- with self . app .test_client () as c :
81+ with app .test_client () as c :
12782 rv = c .get (
12883 '/books/%s/delete' % existing ['id' ],
12984 follow_redirects = True )
13085
13186 assert rv .status == '200 OK'
132-
133- with self .app .test_request_context ():
134- assert not self .model .read (existing ['id' ])
135-
136-
137- @attr ('datastore' )
138- class TestDatastore (CrudTestsMixin , IntegrationBase ):
139- backend = 'datastore'
140-
141-
142- @attr ('cloudsql' )
143- class TestCloudSql (CrudTestsMixin , IntegrationBase ):
144- backend = 'cloudsql'
145-
146-
147- @attr ('mongodb' )
148- class TestMongo (CrudTestsMixin , IntegrationBase ):
149- backend = 'mongodb'
87+ assert not model .read (existing ['id' ])
0 commit comments