How can you perform UI Testing without Using Mocks? - ios

I have SwiftUI application and I need to test my user interface. The interface contains login view, where the button sends a request to the authentication service and get result back. Since, I am not using Mocks how can I test my interface. For the UI Test, I can switch to the test server but then I am very close to writing an end to end test.
Would it make sense to skip UI Tests and simply perform End to End testing with a real test server?

Related

How to test rake task in Minitest?

I have a rake task in my rails application that published jobs to facebook. And then changes some model values. So one way to test the rake task is to invoke the rake task and check values that have been changed.
test 'z' do
# setup some data
Rake::Task['job:publish_to_facebook'].invoke
Rake::Task['job:publish_to_facebook'].reenable
# assert table values that has been changed.
end
But how I can test whether jobs are successfully published on facebook? Is there any better strategy except using capybara and selenium-webdriver ?
Even if i use stubbing and mocking then how can i verify that my jobs are published on facebook?
Most tests should not contact an external API, mainly because it will slow down tests and you might also run into rate limits.
Even if i use stubbing and mocking then how can i verify that my jobs are published on facebook?
The point of stubbing and mocking is precisely not to publish to Facebook. Instead, you would create a class called Facebook (for example) with a method like def post_message(message). This is the app's front door to Facebook, all calls to Facebook go through this class. Then you can use a library like Mocha to overwrite def post_message during testing. You can use it to verify that the application is attempting to post a message, and verify the message itself is correct. It won't actually post the message.
As I mentioned, you do want to make some tests with real calls to Facebook (though not many). These could be in a test like you've shown above, which is an integration test, or it could also be a smaller unit test of the Facebook class I suggested above, which would be a better starting point. For this purpose, you'd want to establish a test account on Facebook. Then your test should clear all messages in the setup and use Facebook's API to verify that the messages were actually posted.

iOS XCtest accessing App View Controllers/UI

I am new to iOS development. I want to write unit tests for an app which uses an SDK where the authenticate method is of the form:
(void)authenticate:(UIViewController *)presentingViewController clearCookies:(BOOL)clearCookies completionBlock:(AuthCompletionBlock)completionBlock.
To authenticate the user, an embedded web browser needs to open in the UIViewController(passed in the method parameters) . Can the unit tests access app UI?
How do I make sure that the browser opens, user authenticates thru app UI and then the unit tests execute.
Depends if you want unit tests or UI tests.
Unit tests: Fast. Consistent. They confirm step-by-step. But they don't go end-to-end.
UI tests: Slow. Fragile. They confirm end-to-end.
For unit testing, you wouldn't write tests that actually bring up a browser or interact with it in any way. Instead, you'd write tests that would bring up the browser, and tests that simulate different inputs returned from the browser.
This works as long as you're confident in the back-and-forth communication. If so, there's no need to test Apple's code. If not, then you can write a spike solution to understand the communication.

Running integration/acceptance tests on the frontend. Need an API for the frontend to tell Rails which database state to set up for each test

My frontend is an EmberJS-based app. It's totally async in nature, so testing it with Capybara is pain and misery. On the other hand, Ember provides a fantastic test suite out of the box which makes acceptance testing fun and effective.
Normally, either fixtures or backend mocks are used to acceptance-test Ember apps. But testing against mocks does not satisfy me at all:
It will not reveal possible API inconsistencies between the backend and the frontend, race conditions, etc.
It is impossible to test backend business logic this way. Such tests are not integration tests.
Finally, acceptance tests require persistency, so you have to replicate backend behavior in a mock. It's very tedious and you effectively end up implementing two backends.
So I want to test against the real backend! It's trivial to set up Ember to use a local backend instance for testing. But the problem is that the backend will persist its state between individual tests and even test sessions.
That's why I'm thinking of implementing a special public API in Rails:
The API is only available when Rails is run with a specific flag or an env var.
Rails runs in a non-testing mode, serving normal API calls as it would in production.
Before each test, the frontend calls the special API, telling Rails which database setup is needed for this specific test.
When a call to the special API is received, Rails cleans the database and populates it with the requested data. For example, to test item deletion from the cart, the database should have three items in the cart.
Rails finishes the API request, and the frontend starts the test.
Frontend runs test steps, using the normal backend API as it would in production: log in, create posts, comment on them. It will also try doing some forbidden things, e. g. edit posts while not logged in, exceed text length constraints, etc and verify whether the backend rejects forbidden actions.
When the frontend runs next test, it will call the special API again. Rails will discard the state produced by the previous test and set up a new one, for this specific test.
I'm a frontend dev with a sketchy knowledge of Rails. Factory Girl and Database Cleaner seem to be the right tools for the job, but there is absolutely no information how to use them outside Rails' normal test environment. I guess I need a controller or a Rails engine or something.
So the question is: how do I make an API in Rails that can be used by the frontend to tell Rails to set up a certain database state with a fixture factory, while Rails are running in a non-test mode i. e. serving REST API and not running through RSpec/Capybara/Cucumber?
Bonus feature: fixture factory properties should be defined on the frontend so that test code is stored in one place. Thus, the backend should be able to accept fixture factory properties via the special API. Defaults can still be defined in the backend's codebase.
I believe this could become an acceptance/integration testing best practice. If I manage to implement it, I promise to publish a gem.
May be something like this
config/routes.rb
namespace 'test_api' do
resource 'db_transaction', only: [:create, :destroy]
end if Rails.env.test?
controllers/test_api/db_transactions_controller.rb
require 'database_cleaner'
def create
DatabaseCleaner.start
end
def destroy
DatabaseCleaner.clean
end

How to test the view using a test server in Rails?

Currently I've got a couple of files in my view that I'm now beginning to design visually (through CSS) by vising the local web app in my browser. To get to these views, you have to go through an authentication step in my application.
Now when testing the authentication step in a controller, I use a fixture containing some test login credentials. This allows me test other parts of the application after this step. However if I wanted to test using the server, I would have to use real credetials from the database. Am I supposed to put fake data in the 'development' database so I can do this, and instead use real data in the 'production' database?
What you're trying to achieve is called integration testing (or end-to-end testing). Rails provides integration testing out of the box.
Personal preferences : I use Cucumber with the Capybara DSL, and seed data corresponding to my features/scenarios using Cucumber's hooks.
EDIT : at first read, I didn't understand that by "testing" you meant "manual testing". In this case yes, you'd better seed your development database with fake data corresponding to your features/test cases.

How should I deal with online dependencies when running Rspec offline?

I would like to run RSpec to test my code both when I'm connected to the web and when I'm not.
Unfortunately there are some tests in the application which are dependent on having a live connection - email sending, Facebook integration etc.
Is there a best-practice way to create an online/offline testing environment or is this bad practice? Judging by how little I can find about this on the web I'm guessing the latter.
Normally in situations like that you would mock the parts of the code that connect outside your application. This allows you to test against the expected results from the service/system you are connecting to. It's also quicker to run tests.
There's a brief tutorial on mocking with rspec here but I'm sure you can find plenty yourself.
For testing that emails get sent there are other approaches if you are sending through ActionMailer. There's a section on that in the rails testing guide.
EDIT (in response to comment):
You could put a method in TestHelper to only run tests when you are online. Something like:
def when_online
if test_remote_connectivity
yield
else
puts "Skipping test offline."
end
end
Then you can call it like:
def test_facebook
when_online do
.....
end
end
Not sure I entirely advocate it but it might do what you want!
You could use webmock inside the tests/specs you don't want connecting to the remote resource.

Resources