Tagged: specs Toggle Comment Threads | Keyboard Shortcuts

  • kmitov 6:18 am on November 30, 2020 Permalink |
    Tags: , , specs,   

    Testing an index page in a web application where we depend on the order. 

    [Everyday Code]

    Today the specs for an index page failed and I had to improve it. I decided to share a little trick for when we depend on the order of the objects.

    The specs is for the /subscriptions page where we show an index of all the subscriptions. We order the subscriptions by created_at in DESC. There are 20 subscriptions on the page. Then you must got to the next page. In the spec we open the page and check that there is a link to our subscription.

    visit "/admin/user/subscriptions"
    
    expect(page).to have_link subscription.random_id.to_s, href: "/admin/user/subscriptions/#{subscription.to_param}/edit"

    The problem was that there are other specs which for some reason create subscriptions into the future. This means that at a certain point in time when more than 20 subscriptions are created into the future in the DB, then our spec will fail. It will fail because the newly created subscription is on the second page.

    All the subscriptions on this page are into the future as today is 2020-11-30. So our newly created subscription is not here.

    What are our options?

    Move to the correct page in the spec

    This is an option. It will require us to have a loop in the spec that would more to the next page in the index and search for each subscription. This is too much logic for a spec.

    Delete all the future subscriptions before starting the spec

    Could be done. But is more logic for the spec. It actually needs to delete subscriptions and this is not the job of this specs.

    Create a subscription that is with the most recent created_at

    It is simple.

      let(:subscription) {FactoryBot.create(:subscription, created_at: subscription_created_at_time)}
    
      def subscription_created_at_time
        (Subscription.order(:created_at).last.try(:created_at) || Time.now)+1.second
      end
    
    

    It is the simpler change for this spec. Just create a subscription that’s last. In this way we know it will appear on the first page even when other specs have created subscriptions into the future.

     
  • kmitov 9:39 pm on November 28, 2020 Permalink |
    Tags: , , specs, ,   

    Why we should never clear our DB before/after running specs. 

    One common “mistake” I’ve seen a couple of times is to clean the Database before/after specs are run. It seems to be a common practice with reasonable arguments. I think this is a bad idea. Here is why and what we should do instead.

    Why is the DB cleared before/after the specs

    When running specs that need access to a DB we might have to create a User or an Article or a Project model, then connect them in a certain way and test the business logic of our spec. After the spec is finished it is not wise to delete these objects from the DB directly in the spec. Sometimes it takes additional time, sometimes it executes additional logic. In most cases you don’t clear the DB after each and every spec.

    It is a good idea to clean the db before all the specs or after all the specs if they are successful. In this way we reset the DB only once, it saves some time and is much cleaner because you can plug in this behavior if you want to.

    Why the DB should not be cleared before/after the specs

    The simple answer is that our code will never, absolutely never work on a clean db in a production. If we have a test procedure that runs the specs against a clean and empty db they might pass when the db is clean. But what use do we have from code that could work in a clean environment, but could not work in a real production environment. The answer is – non.

    We don’t clean our db before/after each spec. In this way we’ve been able to track some really nasty bugs. Like slow queries that are slow only when you have too many users. Other cases involve special relations that are built in time. Like users that are part of an organization and the organization was once having one check for uniqueness of the user and now it has another check. Because the db is not cleared every time we make sure that it is properly migrated with all the needed migrations.

    We found out that a 7 years out test db that is not cleared is closer to a 7 years old production db.

    The test db is not the production db

    The test db is not the production db. It might have the same scheme, that is for sure, but the amount of data in them and the complexity of this data is different. What we need is code that could run on a production db. There is no use of any code that could run only in test environment.

    So here is what we do:

    We export the production db, we change some data like user emails, names and any other sensitive data and we import it as a test db. We run the specs on this db.

    In this way we make sure that the code could actually run on a real db before deploying it.

     
c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel