Testing the ViewModels in Open Event Organizer App

In Open Event Organizer Android App we follow Test Driven Development Approach which means the features added in the app are tested thoroughly by unit tests. More tests would ensure better code coverage and fewer bugs. This blog explains how to write tests for Viewmodel class in MVVM architecture. Specifications We will use JUnit4 to write unit tests and Mockito for creating mocks. The OrdersViewModel class returns the list of Order objects to the Fragment class. The objects are requested from OrderRepository class which fetches them from Network and Database. We will create a mock of OrderRepository class since it is out of context and contain logic that doesn’t depend on Orders Respository. Below is the getOrders method that we will test.  public LiveData<List<Order>> getOrders(long id, boolean reload) { if (ordersLiveData.getValue() != null && !reload) return ordersLiveData; compositeDisposable.add(orderRepository.getOrders(id, reload) .compose(dispose(compositeDisposable)) .doOnSubscribe(disposable -> progress.setValue(true)) .doFinally(() -> progress.setValue(false)) .toList() .subscribe(ordersLiveData::setValue, throwable -> error.setValue(ErrorUtils.getMessage(throwable).toString()))); return ordersLiveData; } We will be using InstantTaskExecutorRule() which is a JUnit Test Rule that swaps the background executor used by the Architecture Components with a different one which executes each task synchronously. We will use setUp() method to load the RxJavaPlugins, RxAndroid plugins and reset them in tearDown method which will ensure each test runs independently from the other and avoid memory leaks. After doing this initialization and basic setup for tests we can begin code the method shouldLoadOrdersSuccessfuly() to test the getOrders method present in ViewModel class. Let’s see the step by step approach. Use Mockito.when to return Observables one by one from ORDERS_LIST whenever the method getOrders of the mock orderRepository is called. We will use Mockito.InOrder and pass orders, orderRepository and progress to check if they are called in a particular order. We will use .observeForever method to observe on LiveData objects and add a ArrayList on change. Finally, we will test and verify if the methods are called in order. @Test public void shouldLoadOrdersSuccessfully() { when(orderRepository.getOrders(EVENT_ID, false)) .thenReturn(Observable.fromIterable(ORDERS_LIST)); InOrder inOrder = Mockito.inOrder(orders, orderRepository, progress); ordersViewModel.getProgress().observeForever(progress); orders.onChanged(new ArrayList<>()); ordersViewModel.getOrders(EVENT_ID, false); inOrder.verify(orders).onChanged(new ArrayList<>()); inOrder.verify(orderRepository).getOrders(EVENT_ID, false); inOrder.verify(progress).onChanged(true); inOrder.verify(progress).onChanged(false); } Similar approach can be followed for writing tests to check other behaviour of the ViewModel. References Official Documentation for testing. https://developer.android.com/reference/android/arch/core/executor/testing/InstantTaskExecutorRule Official Documentation for JUnit.  https://junit.org/junit4/ Official documentation for Mockito.  http://site.mockito.org/ Open Event Organizer App codebase.  https://github.com/fossasia/open-event-orga-app

Continue ReadingTesting the ViewModels in Open Event Organizer App

Deployment terms in Open Event Frontend

In Open Event Frontend, once a pull request is opened, we see some tests running on for the specific pull request like ‘Codacy’, ‘Codecov’, ‘Travis’, etc. New contributors eventually get confused what the tests are about. So this blog would be a walkthrough to these terms that we use and what they mean about the PR. Travis: Everytime you make a pull request, you will see this test running and in some time giving the output whether the test passed or failed. Travis is the continuous integration test that we are using to test that the changes that the pull request you proposed does not break any other things. Sometimes you will see the following message which indicates that your changes is breaking something else which is not intended. Thus, by looking at the Travis logs, you can see where the changes proposed in the pull request are breaking things. Thus, you can go ahead and correct the code and push again to run the Travis build until it passes. Codacy: Codacy is being used to check the code style, duplication, complexity and coverage, etc. When you create a pull request or update the pull request, this test runs which checks whether the code followed certain style guide or if there is duplication in code, etc. For instance let’s say if your code has a html page in which a tag has an attribute which is left undefined. Then codacy will be throwing error failing the tests. Thus you need to see the logs and go correct the bug in code. The following message shows that the codacy test has passed. Codecov: Codecov is a code coverage test which indicates how much of the code change that is proposed in the pull request is actually executed. Consider out of the 100 lines of code that you wrote, only 80 lines is being actually executed and rest is not, then the code coverage decreases. The following indicates the codecov report. Thus, it can be seen that which files are affected by what percent. Surge: The surge link is nothing but the deployment link of the changes in your pull request. Thus, checking the link manually, we can test the behavior of the app in terms of UI/UX or the other features that the pull request adds. References: Travis CI: https://travis-ci.org/ Codacy: https://www.codacy.com/ Codecov: https://codecov.io/    

Continue ReadingDeployment terms in Open Event Frontend

Writing Tests for ISO8601Date.java class of the Open Event Android App

ISO8601Date.java class of Open Event Android App was a util class written to perform the date manipulation functions and ensure the code base got more simpler and deterministic. However it was equally important to test the result from this util class so as to ensure the result returned by it was what we wanted. A test class named “DateTest.java” was written to ensure all the edge cases of conversion of the dates string from one timezone to another timezone were handled properly. For writing unit tests, first we needed to add these libraries as dependencies in the app’s top level build.gradle file as shown below: dependencies { testCompile 'junit:junit:4.12' } Then a JUnit 4 Test class, which was a Java class containing the required test methods was created. The structure of the class looked like this: public class DateTest {    @Test    public void methodName() {    } } Next step was including all the required methods which ensured the util class returned the correct results according to our needs. Various edge cases were taken into account by including functions like converting of date string from local time zone to specified timezone, from international timezone to local timezone, from local timezone to international timezone and many more. Some of the methods which were added in the class are shown below: Test of conversion from local timezone to specified timezone: This function aimed at ensuring the util class worked well with date conversion from local time zone to a specified timezone. An example as shown below was taken where the conversion of the date string was tested from UTC timezone to Singapore timezone. @Test public void shouldConvertLocalTimeZoneDateStringToSpecifiedTimeZoneDateString() { ISO8601Date.setTimeZone("UTC"); ISO8601Date.setEventTimeZone("Asia/Singapore"); String dateString1 = "2017-06-02T07:59:10Z"; String actualString = ISO8601Date.getTimeZoneDateStringFromString(dateString1); String expectedString = "Thu, 01 Jun 2017, 23:59, UTC"; Assert.assertEquals(expectedString, actualString); } Test of conversion from local timezone to international timezone: This function aimed at ensuring the util class worked well with the date conversion from local timezone to international timezone. An example as shown below was taken where the conversion of the date string was tested from Amsterdam timezone to Singapore timezone. @Test public void shouldConvertLocalTimeZoneDateStringToInternationalTimeZoneDateString() { ISO8601Date.setTimeZone("Europe/Amsterdam"); ISO8601Date.setEventTimeZone("Asia/Singapore"); String dateString = "2017-06-02T02:29:10Z"; String actualString = ISO8601Date.getTimeZoneDateStringFromString(dateString); String expectedString = "Thu, 01 Jun 2017, 20:29, GMT+02:00"; Assert.assertEquals(expectedString, actualString); } Above were some functions added to ensure the conversion of a date string from one timezone to another was correct and thus ensured the util class was working properly and returned the results as required. The last thing left was running the test to check the results the util class returned. For this we had to do two things: Sync the project with Gradle. Run the test by right clicking on the class and selecting “Run” option. Through this we were able to run the test and check the output of the util class on different cases through the results which could be seen on the Android Monitor in the Android Studio. Related Links: This link is about building effective unit tests in android.…

Continue ReadingWriting Tests for ISO8601Date.java class of the Open Event Android App

Adding Unit Tests for Services in loklak search

In Loklak search, it can be tricky to write tests for services as these services are customizable and not fixed. Therefore, we need to test every query parameter of the URL. Moreover, we need to test if service is parsing data in a correct manner and returns only data of type ApiResponse. In this blog here, we are going to see how to build different components for unit testing services. We will be going to test Search service in loklak search which makes Jsonp request to get the response from the loklak search.json API which are displayed as feeds on loklak search. We need to test if the service handles the response in a correct way and if the request parameters are exactly according to customization. Service to test Search service in loklak search is one of the most important component in the loklak search. SearchService is a class with a method fetchQuery() which takes parameter and sets up URL parameters for the search.json API of loklak. Now, it makes a JSONP request and maps the API response. The Method fetchQuery() can be called from other components with parameters query and lastRecord to get the response from the server based on a certain search query and the last record to implement pagination feature in loklak search. Now as the data is retrieved, a callback function is called to access the response returned by the API. Now, the response received from the server is parsed to JSON format data to extract data from the response easily. @Injectable() export class SearchService { private static readonly apiUrl: URL = new URL('https://api.loklak.org/api/search.json'); private static maximum_records_fetch = 20; private static minified_results = true; private static source = 'all'; private static fields = 'created_at,screen_name,mentions,hashtags'; private static limit = 10; private static timezoneOffset: string = new Date().getTimezoneOffset().toString();constructor( private jsonp: Jsonp ) { }// TODO: make the searchParams as configureable model rather than this approach. public fetchQuery(query: string, lastRecord = 0): Observable<ApiResponse> { const searchParams = new URLSearchParams(); searchParams.set('q', query); searchParams.set('callback', 'JSONP_CALLBACK'); searchParams.set('minified', SearchService.minified_results.toString()); searchParams.set('source', SearchService.source); searchParams.set('maximumRecords', SearchService.maximum_records_fetch.toString()); searchParams.set('timezoneOffset', SearchService.timezoneOffset); searchParams.set('startRecord', (lastRecord + 1).toString()); searchParams.set('fields', SearchService.fields); searchParams.set('limit', SearchService.limit.toString()); return this.jsonp.get(SearchService.apiUrl.toString(), { search: searchParams }) .map(this.extractData)}private extractData(res: Response): ApiResponse { try { return <ApiResponse>res.json(); } catch (error) { console.error(error); } } Testing the service Create a mock backend to assure that we are not making any Jsonp request. We need to use Mock Jsonp provider for this. This provider sets up MockBackend and wires up all the dependencies to override the Request Options used by the JSONP request. const mockJsonpProvider = { provide: Jsonp, deps: [MockBackend, BaseRequestOptions], useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => { return new Jsonp(backend, defaultOptions); } };   Now, we need to configure the testing module to isolate service from other dependencies. With this, we can instantiate services manually. We have to use TestBed for unit testing and provide all necessary imports/providers for creating and testing services in the unit test. describe('Service: Search', () => { let service: SearchService = null; let backend: MockBackend = null;…

Continue ReadingAdding Unit Tests for Services in loklak search

Adding Unit Test for Reducer in loklak search

Ngrx/store components are an integral part of the loklak search. All the components are dependent on how the data is received from the reducers. Reducer is like a client-side database which stores up all the data received from the API response. It is responsible for changing the state of the application. Reducers also supplies data to the Angular components from the central Store. If correct data is not received by the components, the application would crash. Therefore, we need to test if the reducer is storing the data in a correct way and changes the state of the application as expected. Reducer also stores the current state properties which are fetched from the APIs. We need to check if reducers store the data in a correct way and if the data is received from the reducer when called from the angular components. In this blog, I would explain how to build up different components for unit testing reducers. Reducer to test This reducer is used for store the data from suggest.json API from the loklak server.The data received from the server is further classified into three properties which can be used by the components to show up auto- suggestions related to current search query. metadata: - This property stores the metadata from API suggestion response. entities: - This property stores the array of suggestions corresponding to the particular query received from the server. valid: - This is a boolean which keeps a check if the suggestions are valid or not. We also have two actions corresponding to this reducer. These actions, when called, changes the state properties which , further, supplies data to the components in a more classified manner. Moreover, state properties also causes change in the UI of the component according to the action dispatched. SUGGEST_COMPLETE_SUCCESS: - This action is called when the data is received successfully from the server. SUGGEST_COMPLETE_FAIL: - This action is called when the retrieving data from the server fails. export interface State { metadata: SuggestMetadata; entities: SuggestResults[]; valid: boolean; }export const initialState: State = { metadata: null, entities: [], valid: true };export function reducer(state: State = initialState, action: suggestAction.Actions): State { switch (action.type) { case suggestAction.ActionTypes.SUGGEST_COMPLETE_SUCCESS: { const suggestResponse = action.payload;return { metadata: suggestResponse.suggest_metadata, entities: suggestResponse.queries, valid: true }; }case suggestAction.ActionTypes.SUGGEST_COMPLETE_FAIL: { return Object.assign({}, state, { valid: false }); }default: { return state; } } } Unit tests for reducers Import all the actions, reducers and mocks import * as fromSuggestionResponse from './suggest-response'; import * as suggestAction from '../actions/suggest'; import { SuggestResponse } from '../models/api-suggest'; import { MockSuggestResponse } from '../shared/mocks/suggestResponse.mock';   Next, we are going to test if the undefined action doesn’t a cause change in the state and returns the initial state properties. We will be creating an action by const action = {} as any;  and call the reducer by const result = fromSuggestionResponse.reducer(undefined, action);. Now we will be making assertions with expect() block to check if the result is equal to initialState and all the initial state properties are…

Continue ReadingAdding Unit Test for Reducer in loklak search

Best Practices when writing Tests for loklak Server

Why do we write unit-tests? We write them to ensure that developers’ implementation doesn't change the behaviour of parts of the project. If there is a change in the behaviour, unit-tests throw errors. This keep developers in ease during integration of the software and ensure lower chances of unexpected bugs. After setting up the tests in Loklak Server, we were able to check whether there is any error or not in the test. Test failures didn’t mention the error and the exact test case at which they failed. It was YoutubeScraperTest that brought some of the best practices in the project. We modified the tests according to it. The following are some of the best practices in 5 points that we shall follow while writing unit tests: Assert the assertions There are many assert methods which we can use like assertNull, assertEquals etc. But we should use one which describes the error well (being more descriptive) so that developer's effort is reduced while debugging. Using these assertions related preferences help in getting to the exact errors on test fails, thus helping in easier debugging of the code. Some examples can be:- Using assertThat() over assertTrue assertThat() give more descriptive errors over assertTrue(). Like:- When assertTrue() is used: java.lang.AssertionError: Expected: is <true> but: was <false> at org.loklak.harvester.TwitterScraperTest.testSimpleSearch(TwitterScraperTest.java:142) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at org.hamcr..........   When assertThat() is used: java.lang.AssertionError: Expected: is <true> but: was <false> at org.loklak.harvester.TwitterScraperTest.testSimpleSearch(TwitterScraperTest.java:142) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at org.hamcr...........   NOTE:- In many cases, assertThat() is preferred over other assert method (read this), but in some cases other methods are used to give better descriptive output (like in next examples) Using assertEquals() over assertThat() For assertThat() java.lang.AssertionError: Expected: is "ar photo #test #car https://pic.twitter.com/vd1itvy8Mx" but: was "car photo #test #car https://pic.twitter.com/vd1itvy8Mx" at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20) at org.junit.Assert.assertThat(Ass........   For assertEquals() org.junit.ComparisonFailure: expected:<[c]ar photo #test #car ...> but was:<[]ar photo #test #car ...> at org.junit.Assert.assertEquals(Assert.java:115) at org.junit.Assert.assertEquals(Assert.java:144) at org.loklak.harvester.Twitter.........   We can clearly see that second example gives better error description than the first one.(An SO link) One Test per Behaviour Each test shall be independent of other with none having mutual dependencies. It shall test only a specific behaviour of the module that is tested. Have a look of this snippet. This test checks the method that creates the twitter url by comparing the output url method with the expected output url. @Test public void testPrepareSearchURL() { String url; String[] query = { "fossasia", "from:loklak_test", "spacex since:2017-04-03 until:2017-04-05" }; String[] filter = {"video", "image", "video,image", "abc,video"}; String[] out_url = { "https://twitter.com/search?f=tweets&vertical=default&q=fossasia&src=typd", "https://twitter.com/search?f=tweets&vertical=default&q=fossasia&src=typd", }; // checking simple urls for (int i = 0; i < query.length; i++) { url = TwitterScraper.prepareSearchURL(query[i], ""); //compare urls with urls created assertThat(out_url[i], is(url)); } }   This unit-test tests whether the method-under-test is able to create twitter link according to query or not. Selecting test cases for the test We shall remember that testing is a very costly task in terms of processing. It takes time to execute. That is why, we need to keep the…

Continue ReadingBest Practices when writing Tests for loklak Server

Using MockBackend to test Susper Angular Front-end Code

In this blog, I’ll be sharing how we are testing services which we are using in Susper development.We’re using Angular 4 in our project as tech stack and we use Jasmine for testing purpose. Tests are written to avoid issues which occur again and again. For example: Since we have implemented knowledge graph, we faced a lot of issues like: When a user enters a query, search results appear but knowledge graph does not appear. When a fresh query is entered or page is refreshed, knowledge graph does not appear. The API which we have used is not responding. We overcome this issue by writing test. The data is being taken with the help of an API. So, it will require testing using HTTP. Instead of testing like this, there is a better way by using MockBackend. Testing with MockBackend is a more sensible approach. This allows us to mock our responses and avoid hitting the actual backend which results in boosting our testing. To use the MockBackend feature, it requires creating a mock. For knowledge-service it looks like this: export const MockKnowledgeApi {   results: {     uri: 'http://dbpedia.org/resource/Berlin',     label: 'Berlin',   }   MaxHits: 5 }; To use the MockBackend feature, import MockBackend, MockConnection, BaseRequestOptions and MockKnowledgeApi. import { MockBackend, MockConnection } from '@angular/http/testing'; import { MockKnowledgeApi } from './shared/mock-backend/knowledge.mock'; import { BaseRequestOptions } from '@angular/http'; Create a mock setup. In this case, we will create mock setup w.r.t HTTP because data from API is being returned as HTTP. If data, is being returned in JSON format, create a mock setup w.r.t jsonp. const mockHttp_provider = {   provide: Http,   deps: [MockBackend, BaseRequestOptions],   useFactory: (backend: MockBackend,options: BaseRequestOptions) => {     return new Http(backend, options); } }; Now, describe the test suite. Inside, describe the function, don’t import MockConnection. It will throw error since it is only used to create a fake backend. It should look like this: providers: [   KnowledgeapiService,   MockBackend,   BaseRequestOptions,   mockHttp_provider, ] Define service as KnowledgeService and backend as MockBackend. Inject both the services in beforeEach() function. Now to actually test the service, create a query. const searchquery = 'Berlin'; The written specs should look like this. I won’t go much in detail here, but I’ll cover up the key points of code. it('should call knowledge service API and return the result', () => { backend.connections.subscribe((connection: MockConnection) => { const options = new ResponseOptions({ body: JSON.stringify(MockKnowledgeApi) });connection.mockRespond(new Response(options)); expect(connection.request.method).toEqual(RequestMethod.Get); }); Here, mockRespond will mock our response and it will test whether the service is working or not. Already, we have defined a query. It should have a link to API and should be equal to searchquery which we have defined already as ‘Berlin’. expect(connection.request.url).toBe( `http://lookup.dbpedia.org/api/search/KeywordSearch` + `?&QueryString=${searchquery}` ); At last, it will check if it’s working or not. If it’s working, then test case will pass. Please note, it will not hit the actual backend. service.getsearchresults(searchquery).subscribe((res) => { expect(res).toEqual(MockKnowledgeApi); ); In this way, we have written…

Continue ReadingUsing MockBackend to test Susper Angular Front-end Code

Writing Simple Unit-Tests with JUnit

In the Loklak Server project, we use a number of automation tools like the build testing tool ‘TravisCI’, automated code reviewing tool ‘Codacy’, and ‘Gemnasium’. We are also using JUnit, a java-based unit-testing framework for writing automated Unit-Tests for java projects. It can be used to test methods to check their behaviour whenever there is any change in implementation. These unit-tests are handy and are coded specifically for the project. In the Loklak Server project it is used to test the web-scrapers. Generally JUnit is used to check if there is no change in behaviour of the methods, but in this project, it also helps in keeping check if the website code has been modified, affecting the data that is scraped. Let’s start with basics, first by setting up, writing a simple Unit-Tests and then Test-Runners. Here we will refer how unit tests have been implemented in Loklak Server to familiarize with the JUnit Framework. Setting-UP Setting up JUnit with gradle is easy, You have to do just 2 things:- 1) Add JUnit dependency in build.gradle Dependencies { . . . . . .<other compile groups>. . . compile group: 'com.twitter', name: 'jsr166e', version: '1.1.0' compile group: 'com.vividsolutions', name: 'jts', version: '1.13' compile group: 'junit', name: 'junit', version: '4.12' compile group: 'org.apache.logging.log4j', name: 'log4j-1.2-api', version: '2.6.2' compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.6.2' . . . . . . }   2) Add source for 'test' task from where tests are built (like here). Save all tests in test directory and keep its internal directory structure identical to src directory structure. Now set the path in build.gradle so that they can be compiled. sourceSets.test.java.srcDirs = ['test']   Writing Unit-Tests In JUnit FrameWork a Unit-Test is a method that tests a particular behaviour of a section of code. Test methods are identified by annotation @Test. Unit-Test implements methods of source files to test their behaviour. This can be done by fetching the output and comparing it with expected outputs. The following test tests if twitter url that is created is valid or not that is to be scraped. /** * This unit-test tests twitter url creation */ @Test public void testPrepareSearchURL() { String url; String[] query = {"fossasia", "from:loklak_test", "spacex since:2017-04-03 until:2017-04-05"}; String[] filter = {"video", "image", "video,image", "abc,video"}; String[] out_url = { "https://twitter.com/search?f=tweets&vertical=default&q=fossasia&src=typd", "https://twitter.com/search?f=tweets&vertical=default&q=from%3Aloklak_test&src=typd", "and other output url strings to be matched…..." }; // checking simple urls for (int i = 0; i < query.length; i++) { url = TwitterScraper.prepareSearchURL(query[i], ""); //compare urls with urls created assertThat(out_url[i], is(url)); } // checking urls having filters for (int i = 0; i < filter.length; i++) { url = TwitterScraper.prepareSearchURL(query[0], filter[i]); //compare urls with urls created assertThat(out_url[i+3], is(url)); } }   Testing the implementation of code is useless as it will either make code more difficult to change or tests useless  . So be cautious while writing tests and keep difference between Implementation and Behaviour in mind. This is the perfect example for a simple Unit-Test. As we see there are some points,…

Continue ReadingWriting Simple Unit-Tests with JUnit

Getting code coverage in a Nodejs project using Travis and CodeCov

We had set up unit tests on the webapp generator using mocha and chai, as I had blogged before. But we also need to get coverage reports for each code commit and the overall state of the repo. Since it is hosted on Github, Travis comes to our rescue. As you can see from our .travis.yml file, we already had Travis running to check for builds, and deploying to heroku. Now to enable Codecov, simply go to http://codecov.io and enable your repository (You have to login with Github so see your Github repos) . Once you do it, your dashboard should be visible like this https://codecov.io/github/fossasia/open-event-webapp We use istanbul to get codecoverage. To try it out just use istanbul cover _mocha On the root of your project (where the /test/ folder is ) . That should generate a folder called coverage or lcov. Codecov can read lcov reports. They have provided a bash file which can be run to automatically upload coverage reports. You can run it like this - bash <(curl -s https://codecov.io/bash) Now go back to your codecov dashboard, and your coverage report should show up. If all is well, we can integrate this with travis so that it happens on every code push. Add this to your travis.yml file. script: - istanbul cover _mocha after_success: - bash <(curl -s https://codecov.io/bash) This will ensure that on each push, we run coverage first. And if it is successful, we push the result to codecov. We can see coverage file by file like this And we can see coverage line by line in a file like this  

Continue ReadingGetting code coverage in a Nodejs project using Travis and CodeCov

Unit Testing and Travis

Tests are an important part of any software development process. We need to write test codes for any feature that we develop to check if that feature is working properly. In this post, I am gonna talk about writing Unit tests and running those test codes. If you are a developer, I assume you have heard about unit tests. Most of you probably even wrote one in your life. Unit testing is becoming more and more popular in software development. Let's first talk about what Unit testing is: What is unit testing? Unit testing is the process through which units of source code are tested to verify if they work properly. Performing unit tests is a way to ensure that all functionalities of an application are working as they should. Unit tests inform the developer when a change in one unit interferes with the functionality of another. Modern unit testing frameworks are typically implemented using the same code used by the system under test. This enables a developer who is writing application code in a particular language to write their unit tests in that language as well. What is a unit testing framework? Unit testing frameworks are developed for the purpose of simplifying the process of unit-testing. Those frameworks enable the creation of Test Fixtures, which are classes that have specific attributes enabling them to be picked up by a Test Runner. Although it is possible to perform unit tests without such a framework, the process can be difficult, complicated and very manual. There are a lot of unit testing frameworks available. Each of the frameworks has its own merits and selecting one depends on what features are needed and the level of expertise of the development team. For my project, Engelsystem I choose PHPUnit as the testing framework. PHPUnit With PHPUnit, the most basic thing you’ll write is a test case. A test case is just a term for a class with several different tests all related to the same functionality. There are a few rules you’ll need to worry about when writing your cases so that they’ll work with PHPUnit: The test class would extend the PHPUnit_Framework_TestCase class. The test parameters will never receive any parameters. Below is an example of a test code from my project, Engelsystem <?php class ShiftTypes_Model_test extends PHPUnit_Framework_TestCase { private $shift_id = null; public function create_ShiftType(){ $this->shift_id = ShiftType_create('test', '1', 'test_description'); } public function test_ShiftType_create() { $count = count(ShiftTypes()); $this->assertNotFalse(create_ShiftType($shift_id)); // There should be one more ShiftTypes now $this->assertEquals(count(ShiftTypes()), $count + 1); } public function test_ShiftType(){ $this->create_ShiftType(); $shift_type = ShiftType($this->shift_id); $this->assertNotFalse($shift_type); $this->assertTrue(count(ShiftTypes()) > 0); $this->assertNotNull($shift_type); $this->assertEquals($shift_type['name'], 'test'); $this->assertEquals(count(ShiftTypes()), 0); $this->assertNull(ShiftTypes(-1)); } public function teardown() { if ($this->shift_id != null) ShiftType_delete($this->shift_id); } } ?> We can use different Assertions to test the functionality. We are running these tests on Travis-CI What is Travis-CI? Travis CI is a hosted, distributed continuous integration service used to build and test software projects hosted on GitHub. Open source projects may be tested at no charge via travis-ci.org. Private projects may be tested at…

Continue ReadingUnit Testing and Travis