Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper structure of functional/acceptance tests

I'm currently working on building an automated functional/acceptance test suite for a project, but I don't have a lot of experience writing these types of tests, so I wanted to get some input on properly structuring them. Specifically, I'm working with Arquillian's Graphene extension.

For example, say I have 3 tests, A, B, and C.

TestA : Tests logging into an account in the application. So, if test is successful, the browser should be on the account's home/info page.

TestB : Tests modifying an account's password. This would require logging in to the account, then testing the password change functionality.

TestC : Tests modifying an account's email. This would again require logging in to the account, then testing the email change functionality.

If TestA fails due to a problem with the login code, obviously TestB and TestC should fail, as well, since they require being logged in to an account.

Question: Should automated functional/acceptance tests each duplicate a process that is necessary to complete whatever the test is verifying? In this case, TestB and TestC need to login to the account before doing anything else. Should each test explicitly call something like:

/* ...initial test setup code here */
LoginPage.login(username, password);
assertTrue(onCorrectAccountPage);
AccountModification.changePassword(newPassword);

Or should I use some way of mocking an account into the session that can be used by Tests B and C so that they don't fail even if TestA (the actual login test) does?

Since these are user-acceptance tests, my thought was that they should do exactly what the user would do and log in whenever necessary, but I'm not sure if this is unnecessary duplication that should be handled differently (i.e., treated like units of functionality, similar to a standard unit test) and I wanted to get feedback from someone with more experience in this area.

Thanks in advance. Hopefully my question isn't too convoluted. :)

like image 576
whitlaaa Avatar asked May 10 '12 15:05

whitlaaa


1 Answers

I personally have done it so that each test case replicates the users action as much as possible, but cutting out places where needs be. For example, TestA: logins in, goes to the correct website, goes to it's admin system, finds a user, and deletes part of the users information (such as name), TestB: logins in, goes to the correct website, goes to it's admin system, finds a user, and attempts to delete the users entirely via a button.

TestA and TestB end up on the same page - the user detail page. So in test A, I can do it all properly, exactly how a user does it, but in test B, I go directly to the detail page for that user, as opposed to going through the correct navigation manually. Why?

Saves time, why should I re-do the navigation in test B when test A already tests that anyway?

Remember that tests should not be dependant on each other - if all three tests fail because you cannot login - that's the whole point, you cannot login, so you cannot do any of the other actions.

Think of it as a user would. Each test has their own piece of user-viewable functionality they are testing, but if you cannot login, a user cannot see any of that or do anything with the functionality anyway. If I cannot login, I cannot change my password, or my email - so logically the tests should fail in the same manner.

like image 133
Arran Avatar answered Oct 04 '22 02:10

Arran