You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

323 lines
8.5 KiB

  1. # Go Test Fixtures
  2. [![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/go-testfixtures/testfixtures/blob/master/LICENSE)
  3. [![Join the chat at https://gitter.im/go-testfixtures/testfixtures](https://badges.gitter.im/go-testfixtures/testfixtures.svg)](https://gitter.im/go-testfixtures/testfixtures?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
  4. [![GoDoc](https://godoc.org/gopkg.in/testfixtures.v1?status.svg)](https://godoc.org/gopkg.in/testfixtures.v1)
  5. [![Build Status](https://travis-ci.org/go-testfixtures/testfixtures.svg?branch=master)](https://travis-ci.org/go-testfixtures/testfixtures)
  6. [![Go Report Card](https://goreportcard.com/badge/github.com/go-testfixtures/testfixtures)](https://goreportcard.com/report/github.com/go-testfixtures/testfixtures)
  7. > ***Warning***: this package will wipe the database data before loading the
  8. fixtures! It is supposed to be used on a test database. Please, double check
  9. if you are running it against the correct database.
  10. Writing tests is hard, even more when you have to deal with an SQL database.
  11. This package aims to make writing functional tests for web apps written in
  12. Go easier.
  13. Basically this package mimics the ["Rails' way"][railstests] of writing tests
  14. for database applications, where sample data is kept in fixtures files. Before
  15. the execution of every test, the test database is cleaned and the fixture data
  16. is loaded into the database.
  17. The idea is running tests against a real database, instead of relying in mocks,
  18. which is boring to setup and may lead to production bugs not to being catch in
  19. the tests.
  20. ## Installation
  21. First, get it:
  22. ```bash
  23. go get -u gopkg.in/testfixtures.v2
  24. ```
  25. ## Usage
  26. Create a folder for the fixture files. Each file should contain data for a
  27. single table and have the name `<table-name>.yml`:
  28. ```yml
  29. myapp
  30. - myapp.go
  31. - myapp_test.go
  32. - ...
  33. - fixtures:
  34. - posts.yml
  35. - comments.yml
  36. - tags.yml
  37. - posts_tags.yml
  38. - ...
  39. ```
  40. The file would look like this (it can have as many record you want):
  41. ```yml
  42. # comments.yml
  43. -
  44. id: 1
  45. post_id: 1
  46. content: This post is awesome!
  47. author_name: John Doe
  48. author_email: john@doe.com
  49. created_at: 2016-01-01 12:30:12
  50. updated_at: 2016-01-01 12:30:12
  51. -
  52. id: 2
  53. post_id: 2
  54. content: Are you kidding me?
  55. author_name: John Doe
  56. author_email: john@doe.com
  57. created_at: 2016-01-01 12:30:12
  58. updated_at: 2016-01-01 12:30:12
  59. # ...
  60. ```
  61. Your tests would look like this:
  62. ```go
  63. package myapp
  64. import (
  65. "database/sql"
  66. "log"
  67. _ "github.com/lib/pq"
  68. "gopkg.in/testfixtures.v2"
  69. )
  70. var (
  71. db *sql.DB
  72. fixtures *testfixtures.Context
  73. )
  74. func TestMain(m *testing.M) {
  75. var err error
  76. // Open connection with the test database.
  77. // Do NOT import fixtures in a production database!
  78. // Existing data would be deleted
  79. db, err = sql.Open("postgres", "dbname=myapp_test")
  80. if err != nil {
  81. log.Fatal(err)
  82. }
  83. // creating the context that hold the fixtures
  84. // see about all compatible databases in this page below
  85. c, err = testfixtures.NewFolder(db, &testfixtures.PostgreSQL{}, "testdata/fixtures")
  86. if err != nil {
  87. log.Fatal(err)
  88. }
  89. os.Exit(m.Run())
  90. }
  91. func prepareTestDatabase() {
  92. if err := fixtures.Load(); err != nil {
  93. log.Fatal(err)
  94. }
  95. }
  96. func TestX(t *testing.T) {
  97. prepareTestDatabase()
  98. // your test here ...
  99. }
  100. func TestY(t *testing.T) {
  101. prepareTestDatabase()
  102. // your test here ...
  103. }
  104. func TestZ(t *testing.T) {
  105. prepareTestDatabase()
  106. // your test here ...
  107. }
  108. ```
  109. Alternatively, you can use the `NewFiles` function, to specify which
  110. files you want to load into the database:
  111. ```go
  112. fixtures, err := testfixtures.NewFiles(db, &testfixtures.PostgreSQL{},
  113. "fixtures/orders.yml",
  114. "fixtures/customers.yml",
  115. // add as many files you want
  116. )
  117. if err != nil {
  118. log.Fatal(err)
  119. }
  120. ```
  121. ## Security check
  122. In order to prevent you from accidentally wiping the wrong database, this
  123. package will refuse to load fixtures if the database name (or database
  124. filename for SQLite) doesn't contains "test". If you want to disable this
  125. check, use:
  126. ```go
  127. testfixtures.SkipDatabaseNameCheck(true)
  128. ```
  129. ## Sequences
  130. For PostgreSQL or Oracle, this package also resets all sequences to a high
  131. number to prevent duplicated primary keys while running the tests.
  132. The default is 10000, but you can change that with:
  133. ```go
  134. testfixtures.ResetSequencesTo(10000)
  135. ```
  136. ## Compatible databases
  137. ### PostgreSQL
  138. This package has two approaches to disable foreign keys while importing fixtures
  139. in PostgreSQL databases:
  140. #### With `DISABLE TRIGGER`
  141. This is the default approach. For that use:
  142. ```go
  143. &testfixtures.PostgreSQL{}
  144. ```
  145. With the above snippet this package will use `DISABLE TRIGGER` to temporarily
  146. disabling foreign key constraints while loading fixtures. This work with any
  147. version of PostgreSQL, but it is **required** to be connected in the database
  148. as a SUPERUSER. You can make a PostgreSQL user a SUPERUSER with:
  149. ```sql
  150. ALTER USER your_user SUPERUSER;
  151. ```
  152. #### With `ALTER CONSTRAINT`
  153. This approach don't require to be connected as a SUPERUSER, but only work with
  154. PostgreSQL versions >= 9.4. Try this if you are getting foreign key violation
  155. errors with the previous approach. It is as simple as using:
  156. ```go
  157. &testfixtures.PostgreSQL{UseAlterConstraint: true}
  158. ```
  159. ### MySQL
  160. Just make sure the connection string have
  161. [the multistatement parameter](https://github.com/go-sql-driver/mysql#multistatements)
  162. set to true, and use:
  163. ```go
  164. &testfixtures.MySQL{}
  165. ```
  166. ### SQLite
  167. SQLite is also supported. It is recommended to create foreign keys as
  168. `DEFERRABLE` (the default) to prevent problems. See more
  169. [on the SQLite documentation](https://www.sqlite.org/foreignkeys.html#fk_deferred).
  170. (Foreign key constraints are no-op by default on SQLite, but enabling it is
  171. recommended).
  172. ```go
  173. &testfixtures.SQLite{}
  174. ```
  175. ### Microsoft SQL Server
  176. SQL Server support requires SQL Server >= 2008. Inserting on `IDENTITY` columns
  177. are handled as well. Just make sure you are logged in with a user with
  178. `ALTER TABLE` permission.
  179. ```go
  180. &testfixtures.SQLServer{}
  181. ```
  182. ### Oracle
  183. Oracle is supported as well. Use:
  184. ```go
  185. &testfixtures.Oracle{}
  186. ```
  187. ## Contributing
  188. Tests were written to ensure everything work as expected. You can run the tests
  189. with:
  190. ```bash
  191. # running tests for PostgreSQL
  192. go test -tags postgresql
  193. # running test for MySQL
  194. go test -tags mysql
  195. # running tests for SQLite
  196. go test -tags sqlite
  197. # running tests for SQL Server
  198. go test -tags sqlserver
  199. # running tests for Oracle
  200. go test -tags oracle
  201. # running test for multiple databases at once
  202. go test -tags 'sqlite postgresql mysql'
  203. # running tests + benchmark
  204. go test -v -bench=. -tags postgresql
  205. ```
  206. Travis runs tests for PostgreSQL, MySQL and SQLite.
  207. To set the connection string of tests for each database, edit the `.env`
  208. file, but do not include the changes a in pull request.
  209. ## Changes in v2
  210. A context was created to allow cache of some SQL statements. See in the
  211. documentation above how to use it.
  212. The helpers were renamed to have a smaller name:
  213. ```go
  214. PostgreSQLHelper{} -> PostgreSQL{}
  215. MySQLHelper{} -> MySQL{}
  216. SQLiteHelper{} -> SQLite{}
  217. SQLServerHelper{} -> SQLServer{}
  218. OracleHelper{} -> Oracle{}
  219. ```
  220. The old functions and helpers are still available for backward compatibility.
  221. See the file [deprecated.go](https://github.com/go-testfixtures/testfixtures/blob/master/LICENSE)
  222. ## Alternatives
  223. If you don't think using fixtures is a good idea, you can try one of these
  224. packages instead:
  225. - [factory-go][factorygo]: Factory for Go. Inspired by Python's Factory Boy
  226. and Ruby's Factory Girl
  227. - [go-txdb (Single transaction SQL driver for Go)][gotxdb]: Use a single
  228. database transaction for each functional test, so you can rollback to
  229. previous state between tests to have the same database state in all tests
  230. - [go-sqlmock][gosqlmock]: A mock for the sql.DB interface. This allow you to unit
  231. test database code without having to connect to a real database
  232. There's also these other implementations of test fixtures for Go:
  233. - [go-fixtures][gofixtures]: Django style fixtures for Go
  234. - [mongofixtures][mongofixtures]: Fixtures for MongoDB
  235. - [fixturer][fixturer]: Another fixture loader supporting MySQL
  236. [railstests]: http://guides.rubyonrails.org/testing.html#the-test-database
  237. [gotxdb]: https://github.com/DATA-DOG/go-txdb
  238. [gosqlmock]: https://github.com/DATA-DOG/go-sqlmock
  239. [gofixtures]: https://github.com/AreaHQ/go-fixtures
  240. [mongofixtures]: https://github.com/OwlyCode/mongofixtures
  241. [fixturer]: https://github.com/44hapa/fixturer
  242. [factorygo]: https://github.com/bluele/factory-go