Arranging test environment

In the first step (Arrange) the necessary testing environment is made up for running the test. The effort depends on the test.
If test complexity is unreasonably high and it takes much effort to make up the objects, the problem is more the implementation than the test itself. Then it is rewarding to think about, why the complexity is that high. A test, that is hard to write, is a code smell for a bad implementation.
In general only objects, which are significant for running the test, should be created. Ideally this is just one object: the object under test.

Factories for test object

If it takes some effort to generate test objects, it makes sense to use factories.
This makes maintaining test objects easy. There is just one location: the factory. In Ruby land the Gem FactoryGirl is quite established for that task.

Test objects with predictable data

Test objects should have predictable data. Then and only then the test evidence has a value and is reproducible.
Test objects with random data are more a sign of uncertainty, if all test cases are completely covered.
That is why gems like Faker, generating random data should not be used in the test environment:

Modularize test objects

The more test cases, the more likely test objects of the same type have to have different data. Creating a factory for each test case is awkward.FactoryGirl hast traits for that. A trait is the possibility to set different data, but adopt all other:

Avoid touching the database

In some tests database accesses are necessary, but they slow down the test suite. Doing TDD (Test Driven Development), slow tests are cumbersome. Needless database accesses should be avoided. Once again, if it is costly to test a case, then the implementation probably is not optimal.
If there really is the need for persistence, then as late as possible in the test cycle.
So neither in the factory:

That is how the test performance can be improved. Besides side effects to other tests can be avoided, because the persisted test objects are reasonable.

Stubbing access to external systems

In the tests, accesses to external systems should not be executed for several reasons. They are slow in any case. And they can be problematic, because the external system is productive. Besides the access does not add any value to the test in most cases. The goal is not to test data, but behaviour.
It makes sense to build mocks as external systems or stub the accessing methods out: