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

README.md 9.2 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. # Go Test Fixtures
  2. [![GoDoc](https://godoc.org/gopkg.in/testfixtures.v2?status.svg)](https://godoc.org/gopkg.in/testfixtures.v2)
  3. [![Go Report Card](https://goreportcard.com/badge/github.com/go-testfixtures/testfixtures)](https://goreportcard.com/report/github.com/go-testfixtures/testfixtures)
  4. [![Build Status](https://travis-ci.org/go-testfixtures/testfixtures.svg?branch=master)](https://travis-ci.org/go-testfixtures/testfixtures)
  5. [![Build status](https://ci.appveyor.com/api/projects/status/d2h6gq37wxbus1x7?svg=true)](https://ci.appveyor.com/project/andreynering/testfixtures)
  6. > ***Warning***: this package will wipe the database data before loading the
  7. fixtures! It is supposed to be used on a test database. Please, double check
  8. if you are running it against the correct database.
  9. Writing tests is hard, even more when you have to deal with an SQL database.
  10. This package aims to make writing functional tests for web apps written in
  11. Go easier.
  12. Basically this package mimics the ["Rails' way"][railstests] of writing tests
  13. for database applications, where sample data is kept in fixtures files. Before
  14. the execution of every test, the test database is cleaned and the fixture data
  15. is loaded into the database.
  16. The idea is running tests against a real database, instead of relying in mocks,
  17. which is boring to setup and may lead to production bugs not being caught in
  18. the tests.
  19. ## Installation
  20. First, get it:
  21. ```bash
  22. go get -u -v gopkg.in/testfixtures.v2
  23. ```
  24. ## Usage
  25. Create a folder for the fixture files. Each file should contain data for a
  26. single table and have the name `<table_name>.yml`:
  27. ```
  28. myapp/
  29. myapp.go
  30. myapp_test.go
  31. ...
  32. fixtures/
  33. posts.yml
  34. comments.yml
  35. tags.yml
  36. posts_tags.yml
  37. ...
  38. ```
  39. The file would look like this (it can have as many record you want):
  40. ```yml
  41. # comments.yml
  42. - id: 1
  43. post_id: 1
  44. content: A comment...
  45. author_name: John Doe
  46. author_email: john@doe.com
  47. created_at: 2016-01-01 12:30:12
  48. updated_at: 2016-01-01 12:30:12
  49. - id: 2
  50. post_id: 2
  51. content: Another comment...
  52. author_name: John Doe
  53. author_email: john@doe.com
  54. created_at: 2016-01-01 12:30:12
  55. updated_at: 2016-01-01 12:30:12
  56. # ...
  57. ```
  58. An YAML object or array will be converted to JSON. It can be stored on a native
  59. JSON type like JSONB on PostgreSQL or as a TEXT or VARCHAR column on other
  60. databases.
  61. ```yml
  62. - id: 1
  63. post_attributes:
  64. author: John Due
  65. author_email: john@due.com
  66. title: "..."
  67. tags:
  68. - programming
  69. - go
  70. - testing
  71. post: "..."
  72. ```
  73. If you need to write raw SQL, probably to call a function, prefix the value
  74. of the column with `RAW=`:
  75. ```yml
  76. - id: 1
  77. uuid_column: RAW=uuid_generate_v4()
  78. postgis_type_column: RAW=ST_GeomFromText('params...')
  79. created_at: RAW=NOW()
  80. updated_at: RAW=NOW()
  81. ```
  82. Your tests would look like this:
  83. ```go
  84. package myapp
  85. import (
  86. "database/sql"
  87. "log"
  88. _ "github.com/lib/pq"
  89. "gopkg.in/testfixtures.v2"
  90. )
  91. var (
  92. db *sql.DB
  93. fixtures *testfixtures.Context
  94. )
  95. func TestMain(m *testing.M) {
  96. var err error
  97. // Open connection with the test database.
  98. // Do NOT import fixtures in a production database!
  99. // Existing data would be deleted
  100. db, err = sql.Open("postgres", "dbname=myapp_test")
  101. if err != nil {
  102. log.Fatal(err)
  103. }
  104. // creating the context that hold the fixtures
  105. // see about all compatible databases in this page below
  106.    fixtures, err = testfixtures.NewFolder(db, &testfixtures.PostgreSQL{}, "testdata/fixtures")
  107. if err != nil {
  108. log.Fatal(err)
  109. }
  110. os.Exit(m.Run())
  111. }
  112. func prepareTestDatabase() {
  113. if err := fixtures.Load(); err != nil {
  114. log.Fatal(err)
  115. }
  116. }
  117. func TestX(t *testing.T) {
  118. prepareTestDatabase()
  119. // your test here ...
  120. }
  121. func TestY(t *testing.T) {
  122. prepareTestDatabase()
  123. // your test here ...
  124. }
  125. func TestZ(t *testing.T) {
  126. prepareTestDatabase()
  127. // your test here ...
  128. }
  129. ```
  130. Alternatively, you can use the `NewFiles` function, to specify which
  131. files you want to load into the database:
  132. ```go
  133. fixtures, err := testfixtures.NewFiles(db, &testfixtures.PostgreSQL{},
  134. "fixtures/orders.yml",
  135. "fixtures/customers.yml",
  136. // add as many files you want
  137. )
  138. if err != nil {
  139. log.Fatal(err)
  140. }
  141. ```
  142. ## Security check
  143. In order to prevent you from accidentally wiping the wrong database, this
  144. package will refuse to load fixtures if the database name (or database
  145. filename for SQLite) doesn't contains "test". If you want to disable this
  146. check, use:
  147. ```go
  148. testfixtures.SkipDatabaseNameCheck(true)
  149. ```
  150. ## Sequences
  151. For PostgreSQL or Oracle, this package also resets all sequences to a high
  152. number to prevent duplicated primary keys while running the tests.
  153. The default is 10000, but you can change that with:
  154. ```go
  155. testfixtures.ResetSequencesTo(10000)
  156. ```
  157. ## Compatible databases
  158. ### PostgreSQL
  159. This package has two approaches to disable foreign keys while importing fixtures
  160. in PostgreSQL databases:
  161. #### With `DISABLE TRIGGER`
  162. This is the default approach. For that use:
  163. ```go
  164. &testfixtures.PostgreSQL{}
  165. ```
  166. With the above snippet this package will use `DISABLE TRIGGER` to temporarily
  167. disabling foreign key constraints while loading fixtures. This work with any
  168. version of PostgreSQL, but it is **required** to be connected in the database
  169. as a SUPERUSER. You can make a PostgreSQL user a SUPERUSER with:
  170. ```sql
  171. ALTER USER your_user SUPERUSER;
  172. ```
  173. #### With `ALTER CONSTRAINT`
  174. This approach don't require to be connected as a SUPERUSER, but only work with
  175. PostgreSQL versions >= 9.4. Try this if you are getting foreign key violation
  176. errors with the previous approach. It is as simple as using:
  177. ```go
  178. &testfixtures.PostgreSQL{UseAlterConstraint: true}
  179. ```
  180. ### MySQL / MariaDB
  181. Just make sure the connection string have
  182. [the multistatement parameter](https://github.com/go-sql-driver/mysql#multistatements)
  183. set to true, and use:
  184. ```go
  185. &testfixtures.MySQL{}
  186. ```
  187. ### SQLite
  188. SQLite is also supported. It is recommended to create foreign keys as
  189. `DEFERRABLE` (the default) to prevent problems. See more
  190. [on the SQLite documentation](https://www.sqlite.org/foreignkeys.html#fk_deferred).
  191. (Foreign key constraints are no-op by default on SQLite, but enabling it is
  192. recommended).
  193. ```go
  194. &testfixtures.SQLite{}
  195. ```
  196. ### Microsoft SQL Server
  197. SQL Server support requires SQL Server >= 2008. Inserting on `IDENTITY` columns
  198. are handled as well. Just make sure you are logged in with a user with
  199. `ALTER TABLE` permission.
  200. ```go
  201. &testfixtures.SQLServer{}
  202. ```
  203. ### Oracle
  204. Oracle is supported as well. Use:
  205. ```go
  206. &testfixtures.Oracle{}
  207. ```
  208. ## Generating fixtures for a existing database (experimental)
  209. The following code will generate a YAML file for each table of the database in
  210. the given folder. It may be useful to boostrap a test scenario from a sample
  211. database of your app.
  212. ```go
  213. err := testfixtures.GenerateFixtures(db, &testfixtures.PostgreSQL{}, "testdata/fixtures")
  214. if err != nil {
  215. log.Fatalf("Error generating fixtures: %v", err)
  216. }
  217. ```
  218. Or
  219. ```go
  220. err := testfixtures.GenerateFixturesForTables(
  221. db,
  222. []*TableInfo{
  223. &TableInfo{Name: "table_name", Where: "foo = 'bar'"},
  224. // ...
  225. },
  226. &testfixtures.PostgreSQL{},
  227. "testdata/fixtures",
  228. )
  229. if err != nil {
  230. log.Fatalf("Error generating fixtures: %v", err)
  231. }
  232. ```
  233. > This was thought to run in small sample databases. It will likely break
  234. if run in a production/big database.
  235. ## Contributing
  236. Tests were written to ensure everything work as expected. You can run the tests
  237. with:
  238. ```bash
  239. # running tests for PostgreSQL
  240. go test -tags postgresql
  241. # running test for MySQL
  242. go test -tags mysql
  243. # running tests for SQLite
  244. go test -tags sqlite
  245. # running tests for SQL Server
  246. go test -tags sqlserver
  247. # running tests for Oracle
  248. go test -tags oracle
  249. # running test for multiple databases at once
  250. go test -tags 'sqlite postgresql mysql'
  251. # running tests + benchmark
  252. go test -v -bench=. -tags postgresql
  253. ```
  254. Travis runs tests for PostgreSQL, MySQL and SQLite. AppVeyor run for all
  255. these and also Microsoft SQL Server.
  256. To set the connection string of tests for each database, copy the `.sample.env`
  257. file as `.env` and edit it according to your environment.
  258. ## Alternatives
  259. If you don't think using fixtures is a good idea, you can try one of these
  260. packages instead:
  261. - [factory-go][factorygo]: Factory for Go. Inspired by Python's Factory Boy
  262. and Ruby's Factory Girl
  263. - [go-txdb (Single transaction SQL driver for Go)][gotxdb]: Use a single
  264. database transaction for each functional test, so you can rollback to
  265. previous state between tests to have the same database state in all tests
  266. - [go-sqlmock][gosqlmock]: A mock for the sql.DB interface. This allow you to
  267. unit test database code without having to connect to a real database
  268. - [dbcleaner][dbcleaner] - Clean database for testing, inspired by
  269. database_cleaner for Ruby
  270. [railstests]: http://guides.rubyonrails.org/testing.html#the-test-database
  271. [gotxdb]: https://github.com/DATA-DOG/go-txdb
  272. [gosqlmock]: https://github.com/DATA-DOG/go-sqlmock
  273. [factorygo]: https://github.com/bluele/factory-go
  274. [dbcleaner]: https://github.com/khaiql/dbcleaner