tests for data access (sql queries) functionality - sql

I want to know the best way of testing data access functionality.
I know that it is possible to create mocks to change data layer objects that is using to test business logic.
However is it possible to test if sql queries to database are correct.
Scenario: A method must return employees which were applied for work last month.
I can return list of object and check if each employee's startDate property is correct (last month).
So if it returns 3 employees and they have correct startDate value but there are more two employee in database which aren't returned. How to write test for that case? :)
Thanks in advance.

You set up the test DB so you shold know what data is in it. If you expect 5 employees to be returned from the query and you get only 3, you know there is an error.
You can test the query with different setups: empty table, only new employees, only old employees, a mix of the two (with special care to the borderline cases), etc.

I don't think you need to check the two other employees in the database which aren't returned.
The key is, when setting up your test data, you would want to ensure you have enough records that don't match the criteria (in addition to the records that do match), then you run the fetch and make sure you get back the correct number of records that do match the criteria.
Preparing the test data in this manner ensures that your method is returning the expected results.

Related

Querying via a form with value from textbox as criteria

The situation: metadata about biological specimens are collected in an Access table. The specimens come from human patients and patient data are collected in a separate table. To limit the amount of private health information we have hanging around, the patient database must be updated with new patients only when we actually receive samples from them.
So that the data entry workers know when they need to update the patient table, I want a button in the specimen data entry form that will pass an entered patient id value as criteria to a query.
The query looks like this right now:
SELECT Patients.[Patient id]
FROM Patients
WHERE (((Patients.[Patient id])=[Forms]![Specimen entry]![patient id]));
but it never has results, even when I run it from records that I know correspond to patients in the patient table. How do I fix this?
Suggestions about what to call this situation so that I can make better searches about it would also be appreciated. I'm an Access novice.
The query looks correct, but make sure the WHERE clause is comparing numbers to numbers or strings to strings (not a number to a string). Also confirm that the form and textbox names are correct. A quick test using your query worked for me.
Depending on how you plan to present the information, you can also dynamically create the query in VBA and then pass the information to the form.
For searching, I'd recommend some combination of access, dynamic, query, and vba.
alternative option
If you're only looking to see if a single patient exists in the table, it may be simpler to use the dlookup function:
If IsNull(DLookup("[Patient ID]", "Patients", "[Patient ID]='" & Me.Patient_ID & "'")) Then MsgBox "does not exist"
This will check to see if the patient exists (return a number) or does not exist (returns NULL).
https://support.office.com/en-us/article/DLookup-Function-8896cb03-e31f-45d1-86db-bed10dca5937

Return first 'unsorted' join in Oracle SQL

I have a table 'ACCOUNTS', with fields ACCTNO and ACPARENT. One account can be the parent of another. One account can have many children.
It's been discovered that certain external processes are using the 'first child' in certain reports and outputs - but there's no actual 'reason' for any particular child to be 'first', just an unintended bug in the code.
First step in untangling this - I need a query, that can be re-run (but not often, so optimisation is not really a factor) that will identify, for all accounts that are parents, what their 'first child' is.
Problem - the 'first child' isn't necessarily anything to do with record ID. If I run the following query, for example:
SELECT ACCTNO FROM ACCOUNTS WHERE ACPARENT = '80005217';
I get a result of:
ACCTNO
______
80007325
80007310
80007315
80007298
I can absolutely, 100% confirm that for this particular example, account 80007325 is the account ID being used as the 'first child'.
On the flipside, if I run a naive query of:
SELECT A1.ACCTNO, A2.ACCTNO AS CHILDACCOUNT FROM ACCOUNTS A1
INNER JOIN ACCOUNTS A2 ON A1.ACCTNO = A2.ACPARENT
WHERE A1.ACCTNO IN
(SELECT ACPARENT FROM ACCOUNTS);
then if I scroll down to where 80005217 is the parent account, I see the following list:
CHILDACCOUNT
______
80007298
80007310
80007315
80007325
It's sorted, even though it's exactly not what I want.
Is there a query that will get me a list of what I want in a single query? A list of all parent accounts, and their 'first child' as returned by SQL unsorted?
To guarantee records coming in a fixed order we must provide the database with sort criteria in the ORDER BY clause. If there is no attribute which defines "first-ness" then no guarantee is possible. Without an ORDER BY clause the records are essentially in an uncontrolled order, although because of
database internals they often fall into some kind of pattern.
So, what makes account 80007325 the first child WHERE ACPARENT = '80005217'? Clearly not numerical order. Is there some other criterion? Date created? A flag column? Seems like you need to talk to your users. Do they really care which records come first? All the time or just in some specific report?
If your users cannot specify the criteria there's not much you can do...
...although I might be tempted to sort CHILDACCOUNT numerically by ACCTNO whenever it is displayed. At least that would provide consistency, and the users will get used to it.

SRSS: Dynamic amount of subreports in a report

it might be possible I'm searching for the wrong keywords, but so far I couldn't find anything useful.
My problem is quite simple: At the moment I get a list of individual Ids through a report parameter, I pass them to a procedure and show the results.
The new request is like this: Instead of showing the list for all individuals at once, there should be a list for each individual id.
Since I'm quite a beginner in srss, I thought the easiest approach would be the best: Create a subreport, copy the shown list, and create a subreport per individual id.
The amount of this IDs is dynamic, so I have to create a dynamic amount of subreports.
Funny enought, this doesnt seem to be possible. This http://forums.asp.net/t/1397645.aspx url doesnt show exactly the problem, but it shows the limit of the subreports.
I even ran trough the whole msdn pages starting http://technet.microsoft.com/en-us/library/dd220581.aspx but I couldnt find anything there.
So is there a possibility, to create a loop like:
For each Individual ID in Individual IDs, create a subreport and pass ONE ID to this?
Or is there another approach I should use to make this work?
I tried to create a 'Fake'-Dataset with no sql query but just for iterating the id list, but it seems the dataset needs a data-source...
As usual, thanks so far for all answers!
Matthias Müller
Or is there another approach I should use to make this work?
You didn't provide much detail about what sort of information needs to be included in the subreport, but assuming it's a small amount of data (say, showing a personnel record), and not a huge amount (such as a persons sales for the last year), a List might be the way to go.
I tried to create a 'Fake'-Dataset with no sql query but just for iterating the id list, but it seems the dataset needs a data-source...
All datasets require a data source, though if you're merely hard-coding some fake return data, any data source will do, even a local SQL instance with nothing in it.

How to group records where a subset matches a condition

I have created a Microsoft report in VS2008 that displays details of products that are tested in a factory. Relevant fields to this problem are: SerialNumber (int), Pass (bool).
There is also a record ID which means several entries may exist per SerialNumber.
What we would like the report to show is to be grouped where SerialNumbers have never met the condition Pass=True (i.e. actual rejects) and the rest under where at least one record shows Pass=True.
The expression for the grouping currently is "=Fields!Pass.Value" which splits pass and fail records (and are then sorted etc).
In case anyone else comes up against this and wants to know how I solved it, I added an extra boolean column to the SQL query called 'Reject' which returns true or false and used this to group the report.
As powerful as the reporting can be, it just appears to be quite limited on what it can do with set data beyond Count, CountDistinct etc.

Selecting specific joined record from findAll() with a hasMany() include

(I tried posting this to the CFWheels Google Group (twice), but for some reason my message never appears. Is that list moderated?)
Here's my problem: I'm working on a social networking app in CF on Wheels, not too dissimilar from the one we're all familiar with in Chris Peters's awesome tutorials. In mine, though, I'm required to display the most recent status message in the user directory. I've got a User model with hasMany("statuses") and a Status model with belongsTo("user"). So here's the code I started with:
users = model("user").findAll(include="userprofile, statuses");
This of course returns one record for every status message in the statuses table. Massive overkill. So next I try:
users = model("user").findAll(include="userprofile, statuses", group="users.id");
Getting closer, but now we're getting the first status record for each user (the lowest status.id), when I want to select for the most recent status. I think in straight SQL I would use a subquery to reorder the statuses first, but that's not available to me in the Wheels ORM. So is there another clean way to achieve this, or will I have to drag a huge query result or object the statuses into my CFML and then filter them out while I loop?
You can grab the most recent status using a calculated property:
// models/User.cfc
function init() {
property(
name="mostRecentStatusMessage",
sql="SELECT message FROM statuses WHERE userid = users.id ORDER BY createdat DESC LIMIT 1,1"
);
}
Of course, the syntax of the SELECT statement will depend on your RDBMS, but that should get you started.
The downside is that you'll need to create a calculated property for each column that you need available in your query.
The other option is to create a method in your model and write custom SQL in <cfquery> tags. That way is perfectly valid as well.
I don't know your exact DB schema, but shouldn't your findAll() look more like something such as this:
statuses = model("status").findAll(include="userprofile(user)", where="userid = users.id");
That should get all statuses from a specific user...or is it that you need it for all users? I'm finding your question a little tricky to work out. What is it you're exactly trying to get returned?