I am currently testing a React app using Selenium for Functional Testing. Selenium is used to launch the app on the browser, and simulate user actions and keep asserting/verifying at each step.
However it gets very tedious to debug these tests as the UI automation is heavy as it has to actually launch the browser , wait for pages to load (which at times is a pain given the unstable environments).
I read about some frameworks like chai which are very lightweight and very fast since I do not have to wait for the pages to load.
On similar lines , can anyone suggest me ways to do the complete functional testing of this application where I can bypass the UI actions (as done by Selenium) , for eg. instead of making selenium to go around clicking and simulation user actions on the UI, is there any way we can load a react component and try to simulate certain user actions through the code and then do the functional verification from the DB and also have data providers for my test . For eg - I have a set of data to be passed to my test function , and this test will run for all the set of data and keep asserting respectively.
Will something like unit testing/white box testing work ?
Will testing frameworks like chai help me with this requirement ?
Do suggest me any other approach if you know.
Ok, so this is the testing stack I have used on my projects.
Karma is an example of a test runner
Mocha is an example of a testing framework
Chai is an example of an assertion library
Sinon is an example of a testing plugin
Enzyme is an example for element selection. (Similar to Jquery)
Karma: Test Runner
Karma is a type of test runner which creates a fake server, and then spins up tests in various browsers using data derived from that fake server. Karma is only a test runner, and requires a testing framework such as Mocha to plug into it in order to actually run tests.
I used webpack + karma.conf.js file. to setup the Karma ecosystem. You can setup a command to watch the test cases run in parellel while coding.
Mocha: Testing Framework
The following file uses Mocha as a testing framework, and Chai as an assertion library:
describe('the todo.App', function() {
context('the todo object', function(){
it('should have all the necessary methods', function(){
var msg = "method should exist";
expect(todo.util.trimTodoName, msg).to.exist;
expect(todo.util.isValidTodoName, msg).to.exist;
expect(todo.util.getUniqueId, msg).to.exist;
});
});
});
Distinguish Between Mocha and Chai
We can distinguish between framework (Mocha) methods and assertion library (Chai) methods by looking at the contents of the it block. Methods outside the it block are generally derived from the testing framework. Everything within the it block is code coming from the assertion library. beforeEach, describe, context, it, are all methods extending from Mocha. expect, equal, and exist, are all methods extending from Chai.
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
$window.localStorage.removeItem('com.shortly');
});
it('should have a signup method', function() {
expect($scope.signup).to.be.a('function');
});
All the methods concerned with the testing framework are occurring outside the it block, and all methods concerned with the assertion library are occurring inside the it block. Therefore we can conclude that anything occurring inside the it block is indeed occurring on a lower level of abstraction than the testing framework.
Or in terms of our classification schema, everything occurring inside the it blocks is either part of an assertion library or a part of a testing plugin. The notion that anything inside the it block is occurring on a lower level of abstraction than the testing framework is only a heuristic, that is- it is merely a rule of thumb.
Sinon: Testing Plugin
Sinon is a plugin which hooks into Chai and gives us the ability to perform a more diverse set of tests. Through the Sinon plugin we can create mocks, stubs, and fake servers:
describe('API integration', function(){
var server, setupStub, JSONresponse;
beforeEach(function() {
setupStub = sinon.stub(todo, 'setup');
server = sinon.fakeServer.create();
});
it('todo.setup receives an array of todos when todo.init is called', function () {
});
afterEach(function() {
server.restore();
setupStub.restore();
});
});
Sinon has a bunch of cool features that allow you to really get into the nooks and crannies of your source code and see what is really going on under the hood.
You could use the spy function for event handlers as well
Think this should provide a direction.
Source
Related
I am writing react container components at the moment that use the connect() wrapper/decorator. I'm interested in providing a fake store to my container when I test using mocha and expect / should. After reading the documentation I should export a flat/simple version of my component and then in the test use <Provider ...>. Below is a link to the documentation.
https://github.com/reactjs/redux/blob/master/docs/recipes/WritingTests.md
However I am struggling to find an example/guideline on actually implementing this. I understand the documentation might omit it as its obvious but I am lost trying to hook up my tests.
I have used redux-mock-store before and using Provider around the connected component to test rendering (I used enzyme) and interactions.
To test mapStateToProps:
create mock store with initial state
render component
assert expectations against the component
To test mapDispatchToProps:
create mock store with initial state
render component
trigger action in component
assert expectation against the mock store
I realized that I have been using setTimeout() in my project -maybe- more than I should, I did a quick research and scroll through some open source react projects on Github and decided I should ask about it.
I use setTimeout mostly for changing the classname or adding styles to animate the DOM objects also using CSS transition, one point I thought it will be hard to write unit testing with this many setTimeout.
Since I came from using AngularJS, there is a $timeoutĀ service which has the same functionality with setTimeout, but in testing you can flush the timeout like $timeout.flush() and the timeout ends instantly.
My questions;
Is there an alternative testable way that I can use instead setTimeout (logicly or programaticly)?
Is there any builtin testable function in React does the same thing with setTimeout?
Is there any react addons I can use for "flushable" timeout?
Keep in mind I'm fairly new at reactjs and haven't write any unit test on it yet.
It depends what you are using. There's a sinonjs fake timers (http://sinonjs.org/) and Jest also has this functionality (with an example): https://facebook.github.io/jest/docs/timer-mocks.html
Cheers,
Mariusz
I'm writing React application. I want to test in isolation component that is wired up with Reflux.js store with:
mixins: [
Reflux.connect(CountriesStore)
],
Initialization code of CountresStore calls action that tries to fetch list of countries. This is the stop where some exception is being raised. But I feel that all this fuzz should not occur. I want to conduct unit, not integration testing. So,
Is there a way to mock this CountriesStore prior of it being called during initialization of component?
I'm trying to use jasmine and guard to test an ember based frontend for my rails 3.2 application. For this, I use jasminerice and guard-jasmine, phantomjs. The setup was very easy and simple and I can run some sample specs. When it comes to play with ember, things go mad. I have the spec below that test a video reader class. It should set videoHeight and videoWitdh property with the value of the corresponding video DOM element when calling loadVideo method.
When I run jasmine on my browser the test pass, but when I run it with guard and phantomjs, it fails. I got "Expect undefined to equal 640". It seems that my DOM element is not taking into account when the test run on phantomjs.
describe "VideoReader", ->
it "loads video from video DOM element", ->
videoDOM = Ember.$("<video width='640' height='480'><source src='/test.mp4'></source></video>")[0];
player = Topper.VideoReader.create();
player.loadVideo(videoDOM);
videoHeight = player.get('videoHeight');
videoWidth = player.get('videoWidth');
expect(videoHeight).toEqual(480);
expect(videoWidth).toEqual(640);
Is my spec correctly written ?
You should read the blog post about Testing in Ember.js.
I don't know what your Topper.VideoReader looks like but I guess your problem has to do with manipulating something on the DOM and not giving Ember.js a chance to propagate those changes. In your tests you should wrap your calls which interact with bindings or are manipulating the DOM in an Ember.run(function(){...}) call, as seen in the tests, for example child_views_test.js.
A summary from the discussion below:
If code you want to test interacts with the DOM, wrap it in an Ember.run call.
If you want to test for events which are fired in your code and you don't have control when exactly they are fired, use the asynchronous test features in the testing framework, like QUnit's asyncTest
I have a unit tests for Zend Framework controllers extending Zend_Test_PHPUnit_ControllerTestCase.
The tests are dispatching an action, which forwards to another action, like this:
// AdminControllerTest.php
public testAdminAction()
$this->dispath('/admin/index/index');
// forwards to login page
$this->assertModule('user');
$this->assertController('profile');
$this->assertController('login');
$this->assertResponseCode(401);
}
// NewsControllerTest.php
public testIndexAction()
{
$this->dispatch('/news/index/index');
$this->assertModule('news');
$this->assertController('index');
$this->assertController('index');
$this->assertResponseCode(200);
}
Both of the tests are passing when they are run as a seperate tests.
When I run them in the same test suite, the second one fails.
Instead dispatching /news/index/index the previous request is dispatched (user module).
How to trace this bug? Looks like I have some global state somewhere in the application, but I'm unable do debug this. How can I dump the objects between the tests in the suite? setUpBefore/AfterClass are static, so there are no so many data about the object instances.
I know this is a kind of guess what question. It's hard to provide reliable data here, because they would took to much place, so feel free to ask for details.
The whole unit test setup is more or less like described in: Testing Zend Framework MVC Applications - phly, boy, phly or Testing Zend Framework Controllers Ā« Federico Cargnelutti.
Solution:
I've determined the issue (after a little nap). The problem was not in unit test setup, but in the tested code.
I use different ACL objects based on module name. Which one to use was determined by static call to action helper, which cached the result in a private static variable to speed things up. This cache was executed only when run in a test suite. I just need more unit tests for this code :)
(I'm sorry for such a rubbish post, but I've stuck with this for a day and I hoped someone else experienced similar kind of this Heisenbug with unit tests in general)
You may try clearingrequest and response objects before dispatching each action, like this:
$this->resetRequest()
->resetResponse()
->dispatch('/news/index/index');