For example, the server would response
{
name: "mike",
age: "12",
sex: "male"
}
In my code, I only use name, so my code would be string name = json["name"];
For my unit test, should my unit test case be the actual json result above or just
{
name: "mike",
}
Since I only parse name field?
When writing unit-tests you should be thinking for each test, what the purpose of each test is.
In your example, the goal of one test might be to test if your code extracts the name properly from the server result. But, as the handling of keys and values is part of the language, you don't have to test that this is working for a mixture of keys and values: The expression json["name"] does the actual magic for you. Therefore, you can keep the 'pseudo' server response quite simple - it does not have to be like an actual server response. That is, just using { name: "mike", } would be OK.
There will likely be more test cases, for example to test that your code handles error situations properly, for example if the server responds with an answer that does not have a name - or have two or more names - or looks totally garbled. Again, you would have to define some 'pseudo' server results.
At some point, however, you will have to test your code against the actual server - then you are, however, leaving the realm of unit-testing and enter into integration-testing.
in unit test case, the actual result will be
{
name: "mike",
}
Related
Imagine that we have a game with different types of servers in it to represent different countries. Now, lets say the game only allows users to "buddy" other players that are only in the same server that their account is attached to. As a developer, I am tasked to write a test case only to see if the feature for users to "buddy" one another works. However, here is where my dilemma lies, since I only have to test whether or not a user can "buddy" someone else, do I have to also test if the user cannot add users from another server in this same test case, or should that be written in another test case totally separate from the current one that I am writing?
Yes, you should.
The first test you're describing, where you just test if they can have a buddy, is known as Happy Path testing. You're testing that it works with no exceptions or errors or weird use cases.
Happy Path testing is a good start. Everything else is where the real fun begins.
In your case, the things that come to mind are...
What if they buddy with an invalid buddy?
What if they buddy with someone who is already their buddy?
What if they buddy with something that's not a user?
How these should be organized is a matter of taste. Ideally they're all separate tests. This makes the purpose of each test clear via the test name, and it avoids interactions and dependencies between the tests. Here's a sketch in no particular language.
describe add_buddy {
test happy_path {
assert user.add_buddy(valid_buddy);
assert user.buddies.contains(valid_buddy);
}
test buddy_on_another_server {
buddies = user.buddies;
assert !buddies.contains(invalid_buddy);
assertThrows {
user.add_buddy(invalid_buddy);
} InvalidBuddy;
assert buddies == user.buddies, "buddy list unchanged";
}
test buddy_with_non_user {
buddies = user.buddies;
assertThrows {
user.add_buddy(non_user);
} ArgumentError;
assert buddies == user.buddies, "buddy list unchanged";
}
test buddy_an_existing_buddy {
assert user.add_buddy(valid_buddy);
# Should this return true? False? An exception?
# You have to decide. I decided false.
assert !user.add_buddy(valid_buddy);
# The buddy is only on the list once.
assert user.buddies.numContains(valid_buddy) == 1;
}
}
Things like user and valid_buddy can be created in the setup routine, or better they're available via a fixtures generator such as Factory_Girl.
I'm using grails plugin multi-tenant-single-db. Within that context I need to write a spock test in which we temporarily remove the tenant restrictions. Location is my Tenant, so my method looks like this:
def loadOjectDetails(){
Location.withoutTenantRestriction{
// code here to retrieve specific items to the object to be loaded
render( template: "_loadDetails", model:[ ... ]
}
}
The method runs as expected, but trying to put method under test coverage the error output suggests that:
groovy.lang.MissingMethodException: No signature of method: com.myPackage.myController.Location.withoutTenantRestriction() is applicable for argument types:
and a stacktrace that stems on from there.
Do I need to Stub this? The withoutTenantRestriction is a wrapper around my entire method logic.
UPDATE:
The test code looks like this:
given:
params.id = 3002
currentUser = Mock(User)
criteriaSetup()
controller.getSalesOrder >> salesOrders[2]
when:
controller.loadOrderManageDetails()
then:
(1.._) controller.springSecurityService.getCurrentUser() >> currentUser
expect:
view == 'orderMange/orderManageDetail'
model.orderInstance == salesOrders[2]
Yes! You should be stubbing it as is created at run time not compile time.
You could stub it like below:
Your_Domain.metaClass.withoutTenantRestriction{Closure closure ->
closure.call()
}
This way your regular code will work in test cases. Also,as in withoutTenantRestriction it basically starts a new hibernate session, which doesn't matter much as now you have stubbed the closure, you could perform desired action in place of calling closure.call() only.
Also, same could be applied to withThisTenant.
In integration tests you don't need to stub it as is loading the whole environment.
Hope it helps!!
I'm currently learning Redux.
So far, as I'm discovering how to manage a state app, I don't want to focus on any integration with a framework (like React). I just want to well understand the idea and concepts behind Redux.
I followed courses given by Dan Abramov on egghead.io.
I like the way he explains by testing his app so I started playing with Redux the same way.
I built an app with Redux. Of course it has multiple reducers and actions.
I won't share any code here because it has no particular interest.
It's more a matter of how to deal with tests and Redux.
I don't know if it makes sense to test reducers with their corresponding actions of if I should mock the actions in my tests.
I started by mocking the actions because at first, I thought that it was a good idea to separate my tests and not having dependencies between reducers and actions. (and it's what I've seen in most tutorials. But in tutorials they often build small app).
Now, I figure out that I sometimes end up with a mock different than the corresponding action and even if my tests are fine, it could break in a real app when I'll use dispatch(myAction()) as it will be something different than exepected.
Should I use my actions in my reducers tests ?
Thanks a lot for any explanation about that.
EDIT : Some code to have a better explanation
REDUCER
case CREATE_USER_IN_PROJECT:
currentProject = state.filter(p => p.id === action.payload.idProjet)[0]
indexCurrentProject = state.indexOf(currentProject)
people = [
...currentProject.people,
action.payload.idUser
]
return [
...state.slice(0, indexCurrentProject),
Object.assign({}, currentProject, {people}),
...state.slice(indexCurrentProject + 1)
]
REDUCER'S TEST
it('CREATE_PROJECT if no project should only have the new project', done => {
let idNewProject = uuid.v4()
expect(
projects(undefined, {
type: CREATE_PROJECT,
payload: {
id: idNewProject,
name: 'New project !'
}
})
)
.toEqual([{
id: idNewProject,
name: 'New project !',
people: [],
money: '€',
operations: [],
archived: false,
closed: false
}])
done()
})
So here, instead of having
{
type: CREATE_PROJECT,
payload: {
id: idNewProject,
name: 'New project !'
}
}
Should I call my action createProject('New project !') ?
Thanks for the clarification. Turns out I misunderstood you in my comment. Here's a hopefully more helpful explanation.
You shouldn't use your actual actions, e.g. createProject('New project !'), in testing your reducers.
Reducers are simple state machines that take an input and return an output. Your tests should check they do exactly that, where:
input = previous state > output = next state. And yes it still count as unit-testing (I don't see why it wouldn't).
I found this a good read on how to test reducers
I have been trying to configure offline unit tests for polymer web components that use the latest release of Firebase distributed database. Some of my tests are passing, but others—that look nigh identical to passing ones—are not running properly.
I have set up a project on github that demonstrates my configuration, and I'll provide some more commentary below.
Sample:
https://github.com/doctor-g/wct-firebase-demo
In that project, there are two suites of tests that work fine. The simplest is offline-test, which doesn't use web components at all. It simply shows that it's possible to use the firebase database's offline mode to run some unit tests. The heart of this trick is the in the suiteSetup method shown below—a trick I picked up from nfarina's work on firebase-server.
suiteSetup(function() {
app = firebase.initializeApp({
apiKey: 'fake',
authDomain: 'fake',
databaseURL: 'https://fakeserver.firebaseio.com',
storageBucket: 'fake'
});
db = app.database();
db.goOffline();
});
All the tests in offline-test pass.
The next suite is wct-firebase-demo-app_test.html, which test the eponymous web component. This suite contains a series of unit tests that are set up like offline-test and that pass. Following the idea of dependency injection, the wct-firebase-demo-app component has a database attribute into which is passed the firebase database reference, and this is used to make all the firebase calls. Here's an example from the suite:
test('offline set string from web component attribute', function(done) {
element.database = db;
element.database.ref('foo').set('bar');
element.database.ref('foo').once('value', function(snapshot) {
assert.equal(snapshot.val(), 'bar');
done();
});
});
I have some very simple methods in the component as well, in my attempt to triangulate toward the broken pieces I'll talk about in a moment. Suffice it to say that this test passes:
test('offline push string from web component function', function(done) {
element.database = db;
let resultRef = element.pushIt('foo', 'bar');
element.database.ref('foo').once('value', function(snapshot) {
assert.equal(snapshot.val()[resultRef.key], 'bar');
done();
});
});
and is backed by this implementation in wct-firebase-demo-app:
pushIt: function(at, value) {
return this.database.ref(at).push(value);
},
Once again, these all pass. Now we get to the real quandary. There's a suite of tests for another element, x-element, which has a method pushData:
pushData: function(at, data) {
this.database.ref(at).push(data);
}
The test for this method is the only test in its suite:
test('pushData has an effect', function(done) {
element.database = db;
element.pushData('foo', 'xyz');
db.ref('foo').once('value', function(snapshot) {
expect(snapshot.val()).not.to.be.empty;
done();
});
});
This test does not pass. While this test is running, the console comes up with an error message:
Your API key is invalid, please check you have copied it correctly.
By setting some breakpoints and walking through the execution, it seems to me that this error comes up after the call to once but before the callback is triggered. Note, again, this doesn't happen with the same test structure described above that's in wct-firebase-demo-app.
That's where I'm stuck. Why do offline-test and wct-firebase-demo-app_test suites work fine, but I get this API key error in x-element_test? The only other clue I have is that if I copy in a valid API key into my initializeApp configuration, then I get a test timeout instead.
UPDATE:
Here is a (patched-together) image of my console log when running the tests.:
To illustrate the issue brought up by tony19 below, here's the console log with just pushData has an effect in x-element_test commented out:
The offline-test results are apparently false positives. If you check the Chrome console, offline-test actually throws the same error:
The error doesn't affect the test results most likely because the API key validation occurs asynchronously after the test has already completed. If you could somehow hook into that validation, you'd be able to to catch the error in your tests.
Commenting out all tests except for offline firebase is ok shows the error still occurring, which points to suiteSetup(). Narrowing the problem down further by commenting 2 of the 3 function calls in the setup, we'll see the error is caused by the call to firebase.initializeApp() (and not necessarily related to once() as you had suspected).
One workaround to consider is wrapping the Firebase library in a class/interface, and mocking that for unit tests.
These are my first steps in testing in general so I don't know how to deal with it.
On production I use REST adapter - Fixtures while developing.
For example having this User model:
Sks.User = DS.Model.extend
name: DS.attr("string")
email: DS.attr("string")
gravatar: Ember.computed(->
email = #get("email") || ""
"http://www.gravatar.com/avatar/" + MD5(email)
).property("email")
firstName: Ember.computed(->
fName = #get('name').split(' ')[0]
).property("name")
lastName: Ember.computed(->
lName = #get('name').split(' ')[1]
).property("name")
how can I test it using TDD/BDD with Jasmine? I suppose that I should test the logic: first name, last name and gravatar but how can I translate it into Jasmine? I've read a lot about testing recently but theory you know is different than practice and I just hit the wall. :(
Should I simulate server to get a JSON or should I use fixtures?
I think for unit testing the models, you shouldn't deal with server (or even simulating the server) at all -- that is left up to the adapter. The unit tests for models would be for things like the computed properties (gravatar, firstname, lastname in this case) and other logic (life cycle callbacks, actions, etc). You can test those fairly straightforward -- they're mostly isolated from the server. Something like this:
describe "gravatar property", ->
it "should append the md5 of the email to the gravatar path", ->
user = Sks.User.createRecord name: "my name", email: "abc#def.com"
expect(user.get('gravatar')).toBe "http://www.gravatar.com/avatar/#{MD5(user.get('email')}"
If you're using Ember-Data's RESTAdapter, you can assume that it's well tested (though you might want to write higher level integration tests to show that your models are getting loaded correctly with adapter data). If you're writing your own adapter, you should have a separate unit test for that.
What parts of the application to load
For unit tests, you really only need to load the main namespace (e.g. Sks = Ember.Application.create(...)) and the model definition (e.g. Sks.User = DS.Model.extend(...)) and its dependencies. Everything else can be stubbed by passing in mocks / stubs when you're creating your model (see: What is dependency injection?)
I've had some issues before with Ember's router autoloading in the test environment; you might want to disable the router (although this is only a problem if you're loading everything for your test -- I'm using jasminerice so all the javascript assets are compiled by the Rails server and the tests run in the browser) -- I think in the new Router you can use deferReadiness: http://emberjs.com/api/classes/Ember.Application.html#method_deferReadiness. Previously I was setting autoinit: false.