[unit-testing] Unit tests vs Functional tests

What is the difference between unit tests and functional tests? Can a unit test also test a function?

This question is related to unit-testing testing functional-testing

The answer is


The way I think of it is like this: A unit test establishes that the code does what you intended the code to do (e.g. you wanted to add parameter a and b, you in fact add them, and don't subtract them), functional tests test that all of the code works together to get a correct result, so that what you intended the code to do in fact gets the right result in the system.


AFAIK, unit testing is NOT functional testing. Let me explain with a small example. You want to test if the login functionality of an email web app is working or not, just as a user would. For that, your functional tests should be like this.

1- existing email, wrong password -> login page should show error "wrong password"!
2- non-existing email, any password -> login page should show error "no such email".
3- existing email, right password -> user should be taken to his inbox page.
4- no @symbol in email, right password -> login page should say "errors in form, please fix them!" 

Should our functional tests check if we can login with invalid inputs ? Eg. Email has no @ symbol, username has more than one dot (only one dot is permitted), .com appears before @ etc. ? Generally, no ! That kind of testing goes into your unit tests.

You can check if invalid inputs are rejected inside unit tests as shown in the tests below.

class LoginInputsValidator
  method validate_inputs_values(email, password)
    1-If email is not like [email protected], then throw error.
    2-If email contains abusive words, then throw error.
    3-If password is less than 10 chars, throw error.

Notice that the functional test 4 is actually doing what unit test 1 is doing. Sometimes, functional tests can repeat some (not all) of the testing done by unit tests, for different reasons. In our example, we use functional test 4 to check if a particular error message appears on entering invalid input. We don't want to test if all bad inputs are rejected or not. That is the job of unit tests.


very simply we can say:

  • black box: user interface test like functional test
  • white box: code test like unit test

read more here.


In Rails, the unit folder is meant to hold tests for your models, the functional folder is meant to hold tests for your controllers, and the integration folder is meant to hold tests that involve any number of controllers interacting. Fixtures are a way of organizing test data; they reside in the fixtures folder. The test_helper.rb file holds the default configuration for your tests. u can visit this.


UNIT TESTING

Unit testing includes testing of smallest unit of code which usually are functions or methods. Unit testing is mostly done by developer of unit/method/function, because they understand the core of a function. The main goal of the developer is to cover code by unit tests.

It has a limitation that some functions cannot be tested through unit tests. Even after the successful completion of all the unit tests; it does not guarantee correct operation of the product. The same function can be used in few parts of the system while the unit test was written only for one usage.

FUNCTIONAL TESTING

It is a type of Black Box testing where testing will be done on the functional aspects of a product without looking into the code. Functional testing is mostly done by a dedicated Software tester. It will include positive, negative and BVA techniques using un standardized data for testing the specified functionality of product. Test coverage is conducted in an improved manner by functional tests than by unit tests. It uses application GUI for testing, so it’s easier to determine what exactly a specific part of the interface is responsible for rather to determine what a code is function responsible for.


  • A unit test tests an independent unit of behavior. What is a unit of behavior? It's the smallest piece of the system that can be independently unit tested. (This definition is actually circular, IOW it's really not a definition at all, but it seems to work quite well in practice, because you can sort-of understand it intuitively.)

  • A functional test tests an independent piece of functionality.


  • A unit of behavior is very small: while I absolutely dislike this stupid "one unit test per method" mantra, from a size perspective it is about right. A unit of behavior is something between a part of a method and maybe a couple of methods. At most an object, but not more than one.

  • A piece of functionality usually comprises many methods and cuts across several objects and often through multiple architectural layers.


  • A unit test would be something like: when I call the validate_country_code() function and pass it the country code 'ZZ' it should return false.

  • A functional test would be: when I fill out the shipping form with a country code of ZZ, I should be redirected to a help page which allows me to pick my country code out of a menu.


  • Unit tests are written by developers, for developers, from the developer's perspective.

  • Functional tests may be user facing, in which case they are written by developers together with users (or maybe with the right tools and right users even by the users themselves), for users, from the user's perspective. Or they may be developer facing (e.g. when they describe some internal piece of functionality that the user doesn't care about), in which case they are written by developers, for developers, but still from the user's perspective.


  • In the former case, the functional tests may also serve as acceptance tests and as an executable encoding of functional requirements or a functional specification, in the latter case, they may also serve as integration tests.

  • Unit tests change frequently, functional tests should never change within a major release.



"Functional test" does not mean you are testing a function (method) in your code. It means, generally, that you are testing system functionality -- when I run foo file.txt at the command line, the lines in file.txt become reversed, perhaps. In contrast, a single unit test generally covers a single case of a single method -- length("hello") should return 5, and length("hi") should return 2.

See also IBM's take on the line between unit testing and functional testing.


Unit Test:- Unit testing is particularly used to test the product component by component specially while the product is under development. Junit and Nunit type of tools will also help you to test the product as per the Unit. **Rather than solving the issues after the Integration it is always comfortable to get it resolved early in the development.

Functional Testing:- As for as the Testing is concerned there are two main types of Testing as 1.Functional Test 2.Non-Functional Test.

Non-Functional Test is a test where a Tester will test that The product will perform all those quality attributes that customer doesn't mention but those quality attributes should be there. Like:-Performance,Usability,Security,Load,Stress etc. but in the Functional Test:- The customer is already present with his requirements and those are properly documented,The testers task is to Cross check that whether the Application Functionality is performing according to the Proposed System or not. For that purpose Tester should test for the Implemented functionality with the proposed System.


Unit testing is usually done by developers. The objective of doing the same is to make sure their code works properly. General rule of thumb is to cover all the paths in code using unit testing.

Functional Testing: This is a good reference. Functional Testing Explanation


Unit Tests are written from a programmers or developers perspective. They are made to ensure that a particular method (or a unit) of a class performs a set of specific tasks.

Functional Tests are written from the user's perspective. They ensure that the system is functioning as users are expecting it to.


The basic distinction, though, is that functional tests test the application from the outside, from the point of view of the user. Unit tests test the application from the inside, from the point of view of the programmer. Functional tests should help you build an application with the right functionality, and guarantee you never accidentally break it. Unit tests should help you to write code that’s clean and bug free.

Taken from "Python TDD" book by Harry Percival


TLDR:

To answer the question: Unit Testing is a subtype of Functional Testing.


There are two big groups: Functional and Non-Functional Testing. The best (non-exhaustive) illustration that I found is this one (source: www.inflectra.com):

enter image description here

(1) Unit Testing: testing of small snippets of code (functions/methods). It may be considered as (white-box) functional testing.

When functions are put together, you create a module = a standalone piece, possibly with a User Interface that can be tested (Module Testing). Once you have at least two separate modules, then you glue them together and then comes:

(2) Integration Testing: when you put two or more pieces of (sub)modules or (sub)systems together and see if they play nicely together.

Then you integrate the 3rd module, then the 4th and 5th in whatever order you or your team see fit, and once all the jigsaw pieces are placed together, comes

(3) System Testing: testing SW as a whole. This is pretty much "Integration testing of all pieces together".

If that's OK, then comes

(4) Acceptance Testing: did we build what the customer asked for actually? Of course, Acceptance Testing should be done throughout the lifecycle, not just at the last stage, where you realise that the customer wanted a sportscar and you built a van.

enter image description here


According to ISTQB those two are not comparable. Functional testing is not integration testing.

Unit test is one of tests level and functional testing is type of testing.

Basically:

The function of a system (or component) is 'what it does'. This is typically described in a requirements specification, a functional specification, or in use cases.

while

Component testing, also known as unit, module and program testing, searches for defects in, and verifies the functioning of software (e.g. modules, programs, objects, classes, etc.) that are separately testable.

According to ISTQB component/unit test can be functional or not-functional:

Component testing may include testing of functionality and specific non-functional characteristics such as resource-behavior (e.g. memory leaks), performance or robustness testing, as well as structural testing (e.g. decision coverage).

Quotes from Foundations of software testing - ISTQB certification


My vision is

  • Unit testing. In Procedural programming unit is a procedure, in Object oriented programming unit is a class. Unit is isolated and reflects a developer perspective
  • Functional testing - more than Unit. User perspective, which describes a feature, use case, story...
    • Integration testing - check if all separately developed components work together. It can be other application, service, library, database, network etc.
      • Narrow integration test - double[About] is used. The main purpose is to check if component is configured in a right way
      • Broad integration test (End to End test, System test) - live version. The main purpose is to check if all components are configured in a right way
    • UI testing - checks if user input triggers a correct action and the UI is changed when some actions are happened
    • ...
  • Non functional testing - other cases
    • Performance testing - calculate a speed and other metrics
    • Usability testing - UX
    • ...

Unit tests tell a developer that the code is doing things right; functional tests tell a developer that the code is doing the right things.

You can read more at Unit Testing versus Functional Testing


A well explained real-life analogy of unit testing and functional testing can be described as follows,

Many times the development of a system is likened to the building of a house. While this analogy isn't quite correct, we can extend it for the purposes of understanding the difference between unit and functional tests.

Unit testing is analogous to a building inspector visiting a house's construction site. He is focused on the various internal systems of the house, the foundation, framing, electrical, plumbing, and so on. He ensures (tests) that the parts of the house will work correctly and safely, that is, meet the building code.

Functional tests in this scenario are analogous to the homeowner visiting this same construction site. He assumes that the internal systems will behave appropriately, that the building inspector is performing his task. The homeowner is focused on what it will be like to live in this house. He is concerned with how the house looks, are the various rooms a comfortable size, does the house fit the family's needs, are the windows in a good spot to catch the morning sun.

The homeowner is performing functional tests on the house. He has the user's perspective.

The building inspector is performing unit tests on the house. He has the builder's perspective.


As a summary,

Unit Tests are written from a programmers perspective. They are made to ensure that a particular method (or a unit) of a class performs a set of specific tasks.

Functional Tests are written from the user's perspective. They ensure that the system is functioning as users are expecting it to.