10 Testing and Profiling Java Application Projects

JDeveloper provides a suite of tools for analyzing the quality and performance of your Java code. It provides features for unit testing your Java projects. Use these tools to improve both the quality of your code and your own programming skills.

This chapter includes the following sections:

10.1 About Testing and Profiling Java Application Projects

The profiler gathers statistics on your program that enable you to diagnose performance issues. It monitors and logs a running program's use of processor and memory resources. It also gathers statistics that enables you to more easily diagnose the performance issues and correct the inefficiencies in your code.

To test your application, JDeveloper provides JUnit wizards, accessible from the New Gallery, to create test fixtures, cases, and suites. Automated testing tools such as JUnit make it easier to perform regular, reliable unit testing. JUnit is an optional feature that can be installed and integrated with JDeveloper.

10.2 Profiling Applications

The Profiler monitors and logs a running program's use of processor and memory resources. It gathers statistics that enables you to more easily diagnose the performance issues and correct the inefficiencies in your code.

The JDeveloper profiling tool which can operate in three modes:

  • Monitor for no-overhead monitoring including JVM telemetry graphs and threads time line. Choose this to obtain high-level information about properties of the target JVM, including thread activity and memory allocations

  • CPU for quick sampling or highly customizable performance profiling utilizing dynamic bytecode instrumentation. Choose this to obtain detailed data on application performance, including the time to execute methods and the number of times the method is invoked.

  • Memory profiling including the Surviving Generations metric for identifying certain types of memory leaks. Choose this to obtain detailed data on object allocation and garbage collection.

It also provides a .hprof viewer called HeapWalker.

10.2.1 About the CPU Profiler

The CPU Profiler is used to analyze your application's impact on the processor. It enables you to identify the methods and threads in your program that consume most of the CPU time. Use the CPU Profiler to test functions of your application, such as startup and initialization, repainting, and compiling. The CPU profiler gathers and displays statistical data about the performance of your application.

The profiler has two tools for CPU profiling:

  • Quick (sampled) - sample the application and take a stack trace periodically. This option is less precise than instrumenting methods, however, the overhead is lower. This option can help you locate methods that you might want to instrument.

  • Advanced (instrumented) - instruments all the methods of the profiled application.You can choose to limit the part of the application's code that is instrumented by defining root methods. This option can greatly reduce the profiling overhead.

10.2.2 About the Memory Profiler

The Memory Profiler enables you to find out how your program is using the Java heap. You can find memory leaks, inefficient heap usage, and in general any suspect memory behavior. The profiler has two tools for memory profiling:

  • Quick (sampled) - samples the application and takes a stack trace periodically. This option is less precise than instrumenting methods, but the overhead is lower. This option can help you locate methods that you might want to instrument.

  • Advanced (instrumented) - instruments all the methods of the profiled application. You can choose to limit the part of the application's code that is instrumented by defining root methods. This option can greatly reduce the profiling overhead.

10.2.3 How to Start a Profiling Session

If you have a project that is targeted to run on your local machine, you can profile the project without any additional configuration. When you profile a local project, you launch the project and start the profiling session from within JDeveloper.

If you want to profile a local application but you cannot or do not want to start the application from JDeveloper, you can profile the application by attaching the IDE to the application. For more information, see Section 10.2.14, "Profiling Using Attach Mode".

To profile a local project, the project must be open in the editor. Before you can use the profiler in the IDE, you need to calibrate the profiler. You only need to calibrate the profiler once. For more information, see Section 10.2.6, "How to Calibrate the Profiler." The first time you profile a project, the IDE needs to modify the project build script to integrate the profiler. The IDE creates a backup of your project build script before it performs the modifications.

You can configure settings to specify that specific operations are performed by the IDE during a profiling session. For example, you can have the IDE open live results for CPU or Memory analysis, always show the threads view, always save a heap dump to the profiled project and more.

To configure profiling settings:

  1. Choose Tools > Preferences > Profiler.

  2. On the Profiler page, set the port number and specify the settings you want.

  3. Click OK.

To start a profiling session:

  • From the main menu, click Run > Profiler <project_name>

    To attach the profiler, from the main menu, click Run > Attach Profiler.

10.2.4 About Profiling Windows

When profiling an application, the IDE provides a set of windows that enable you to control the profiling process and to view the profiling results. You can open the following windows by choosing Window > Profiling > window-name (for example, Window > Profiling > Profiling Points).

The following windows enable you to control and configure the profiling session:

  • Profiler window - This window contains controls enabling you to start, stop and modify profiling sessions, to open windows that display profiling results, and to manage snapshots.

  • Profiling Points window - This window enables you to view and manage profiling points.

The Profiler uses the following windows to display profiling results:

  • Live Profiling Results

  • Telemetry Overview window

  • VM Telemetry window

  • Profiling Threads window

  • Snapshots window

  • Heap window

10.2.5 About Profiling Results

The profiling results obtained from a profiling session depend upon the profiling task you select. When a profiling session is in progress, you can see the live results of the profiling task. At any point during the profiling session you can capture and save the results.

Live Results

The Live Results window show the results of the profiling task over time while the profiling session is in progress.

  • VM Telemetry - The VM Telemetry window displays high-level data on thread activity and memory heap and garbage collection in the VM.

  • Threads - The Threads window displays detailed information about application thread activity.

  • Telemetry Overview - The Telemetry Overview window displays smaller versions of the graphs that are presented in the VM Telemetry window.

  • Live Profiling Results - The Live Profiling Results window displays the live data from the running profiling session. The live results displayed depend on the selected profiling task.

    Note:

    The Live Profiling Results view is not available when you are monitoring an application.

You can open any of these windows by choosing Window > Profiling > window name from the main menu.

Captured Results

The captured results windows show profiling data at a certain point in time during the profiling session. You can capture results at any time during a profiling session and save the results to your project or local system. You do not need to be running a profiling session to view saved captured results.

  • Snapshot - This view displays the captured results of a profiling session. The data contained in the snapshot depends upon the profiling task that is running when the snapshot is taken.

  • Heap - This view displays a heap dump. In this view you can examine the contents of the heap.

  • Save view as image - You can save a .png image of the current view displayed in the Live Results window using Save Current View to Image button in the toolbar. This button is available only if the profile view supports saving to an image. Specify the file or directory to save the image to and click Save in the Select File or Directory dialog.

10.2.6 How to Calibrate the Profiler

You need to calibrate the IDE before you can use the IDE to profile an application. You need to run the calibration process for each JDK you will use for profiling. You do this because instrumenting the bytecode of the application imposes some overhead, and the time spent in code instrumentation needs to be "factored out" in order to achieve more accurate results.

To calibrate the IDE to the local system:

  1. Close any other programs that are running.

    The IDE will run the calibration if other applications are running, but running any CPU-intensive programs when performing the calibration may affect the accuracy of profiling results.

  2. From the Main menu, choose Run > Profiler > Run Profiler Calibration.

  3. Choose the Java Platform that will be used for profiling and click OK.

    Note:

    The Java Platform is available for calibration only if it is added to Java SE Definitions on Tools > Manage Libraries page.

    When you click OK, the IDE will collect calibration data on the selected Java platform. When the calibration process is complete you can start using the IDE to profile your applications.

    You should not share calibration data between various computers or systems.

    Note:

    You only need to calibrate the IDE once for each JDK you will use. However, you should run the calibration process again when anything changes on your local or remote configuration that could affect system performance. The following could affect system performance:
    • Any hardware upgrade

    • Any significant change or upgrade of the operating system

    • An upgrade of the Java platform used for profiling

10.2.7 How to Take a Heap Dump

You can take a heap dump when a profiling session is in progress. When you take a heap dump you are prompted to save the heap to your project or local file system. After you save a heap dump you can load the heap dump at any time and browse the objects on the heap, locate references to individual objects and compare heap dumps to view the differences between the snapshots. You do not need to have a running profiling session to load and browse the heap dump.

The application must be running on JDK 1.5.0_12 or higher to take a heap dump.

To take a heap dump using a profiling point:

  1. Open the source file containing the code where you want to place the profiling point.

  2. Right-click in the line of code where you want to place the profiling point and select Add Profiling Point.

  3. In the Profiling Point Type list, select one of the following snapshot options and click Next:

    • Take Snapshot

    • Timed Take Snapshot

    • Triggered Take Snapshot

  4. In the Customize Properties page of the wizard, select Heap Dump as the type of snapshot and modify any additional settings. The Heap Dump option is available under Settings > Take.

When you use a profiling point to take a heap dump, you specify the point in your source code where you want to place the profiling point. For example, you may want to take a heap dump when a thread enters a specific method.

To take a heap dump on OutOfMemory error:

  1. From the Main menu, select Tools > Preferences > Profiler.

  2. In the On OutOfMemoryError list, select an option from the drop-down list to specify what the IDE does when an OutOfMemoryError is encountered.

    The default behavior is to save the heap dump to the profiled project.

10.2.8 How to Analyze a Heap Dump Using Object Query Language (OQL)

OQL is a SQL-like query language to query a Java heap that enables you to filter/select information wanted from the Java heap. While pre-defined queries such as "show all instances of class X" are already supported by the tool, OQL adds more flexibility. OQL is based on JavaScript expression language.

When you load a Java heap in the Heap window, you can click the OQL Console tab of the window to open the OQL editor. The OQL Console contains an OQL editor, a saved OQL queries window and a window that displays the query results. You can use any of the sample OQL queries or create a query to filter and select heap data to locate the information that you want from the Java heap. After you choose or write a query, you can run the query against the Java heap and view the results.

An OQL query is of the following form:

select <JavaScript expression to select>
[ from [instanceof] <class name> <identifier>
[ where <JavaScript boolean expression to filter> ] ]

where class name is fully qualified Java class name (example: java.net.URL) or array class name. char[] (or [C) is char array name, java.io.File (or [Ljava.io.File;) is name of java.io.File[] and so on. Note that fully qualified class name does not always uniquely identify a Java class at runtime. There may be more than one Java class with the same name but loaded by different loaders. So, class name is permitted to be id string of the class object. If instanceof keyword is used, subtype objects are selected. If this keyword is not specified, only the instances of exact class specified are selected. Both from and where clauses are optional.

In select and (optional) where clauses, the expression used in JavaScript expression. Java heap objects are wrapped as convenient script objects so that fields may be accessed in natural syntax. For example, Java fields can be accessed with obj.field_name syntax and array elements can be accessed with array[index] syntax. Each Java object selected is bound to a JavaScript variable of the identifier name specified in from clause.

10.2.8.1 OQL Examples

Select all Strings of length 100 or more:

select s from java.lang.String s where s.count >= 100

Select all int arrays of length 256 or more:

select a from int[] a where a.length >= 256

Show content of Strings that match a regular expression:

select {instance: s, content: s.toString()} from java.lang.String s
    where /java/(s.toString())

Show path value of all File objects:

select file.path.toString() from java.io.File file

Show names of all ClassLoader classes:

select classof(cl).name 
    from instanceof java.lang.ClassLoader cl

Show instances of the Class identified by given id string:

select o from instanceof 0xd404b198 o

0xd404b198 is id of a Class (in a session). This is found by looking at the id shown in that class's page.

10.2.8.2 OQL built-in objects and functions

Heap object

The heap built-in object supports the following methods:

  • heap.forEachClass - calls a callback function for each Java Class

    heap.forEachClass(callback);
    
  • heap.forEachObject - calls a callback function for each Java object

    heap.forEachObject(callback, clazz, includeSubtypes);
    

    clazz is the class whose instances are selected. If not specified, defaults to java.lang.Object. includeSubtypes is a boolean flag that specifies whether to include subtype instances or not. Default value of this flag is true.

  • heap.findClass - finds Java Class of given name

    heap.findClass(className);
    

    where className is name of the class to find. The resulting Class object has following properties:

    • name - name of the class.

    • superclass - Class object for super class (or null if java.lang.Object).

    • statics - name, value pairs for static fields of the Class.

    • fields - array of field objects. field object has name, signature properties.

    • loader - ClassLoader object that loaded this class.

    Class objects have the following methods:

    • isSubclassOf - tests whether given class is direct or indirect subclass of this class or not.

    • isSuperclassOf - tests whether given Class is direct or indirect superclass of this class or not.

    • subclasses - returns array of direct and indirect subclasses.

    • superclasses - returns array of direct and indirect superclasses.

  • heap.findObject - finds object from given object id

    heap.findObject(stringIdOfObject);
    
  • heap.classes - returns an enumeration of all Java classes

  • heap.objects - returns an enumeration of Java objects

    heap.objects(clazz, [includeSubtypes], [filter])
    

    clazz is the class whose instances are selected. If not specified, defaults to java.lang.Object. includeSubtypes is a boolean flag that specifies whether to include subtype instances or not. Default value of this flag is true. This method accepts an optional filter expression to filter the result set of objects.

  • heap.finalizables - returns an enumeration of Java objects that are pending to be finalized.

  • heap.livepaths - return an enumeration of paths by which a given object is alive. This method accepts optional second parameter that is a boolean flag. This flag tells whether to include paths with weak reference(s) or not. By default, paths with weak reference(s) are not included.

    select heap.livepaths(s) from java.lang.String s
    

    Each element of this array itself is another array. The later array is contains an objects that are in the 'reference chain' of the path.

  • heap.roots - returns an Enumeration of Roots of the heap.

    Each Root object has the following properties:

    • id - String id of the object that is referred by this root

    • type - descriptive type of Root (JNI Global, JNI Local, Java Static, etc.)

    • description - String description of the Root

    • referrer - Thread Object or Class object that is responsible for this root or null

Examples

  • Access static field 'props' of class java.lang.System

    select heap.findClass("java.lang.System").statics.props
    select heap.findClass("java.lang.System").props
    
  • Get number of fields of java.lang.String class

    select heap.findClass("java.lang.String").fields.length
    
  • Find the object whose object id is given

    select heap.findObject("0xf3800b58")
    
  • Select all classes that have name pattern java.net.*

    select filter(heap.classes(), "/java.net./(it.name)")
    

Functions on individual objects

  • allocTrace function

    Returns allocation site trace of a given Java object if available. allocTrace returns array of frame objects. Each frame object has the following properties:

    • className - name of the Java class whose method is running in the frame.

    • methodName - name of the Java method running in the frame.

    • methodSignature - signature of the Java method running in the frame.

    • sourceFileName - name of source file of the Java class running in the frame.

    • lineNumber - source line number within the method.

  • classof function

    Returns class object of a given Java object. The resulting object supports the following properties:

    • name - name of the class

    • superclass - class object for super class (or null if java.lang.Object)

    • statics - name, value pairs for static fields of the class

    • fields - array of field objects. Field objects have name, signature properties

    • loader - ClassLoader object that loaded this class.

    Class objects have the following methods:

    • isSubclassOf - tests whether given class is direct or indirect subclass of this class or not

    • isSuperclassOf - tests whether a given class is direct or indirect superclass of this class or not

    • subclasses - returns array of direct and indirect subclasses

    • superclasses - returns array of direct and indirect superclasses

    Examples

    • Show class name of each Reference type object

      select classof(o).name from instanceof java.lang.ref.Reference o
      
    • Show all subclasses of java.io.InputStream

      select heap.findClass("java.io.InputStream").subclasses()
      
    • Show all superclasses of java.io.BufferedInputStream

      show all superclasses of java.io.BufferedInputStream 
      
  • forEachReferrer function

    Calls a callback function for each referrer of a given Java object.

  • identical function

    Returns whether two given Java objects are identical or not, for example:

    select identical(heap.findClass("Foo").statics.bar, heap.findClass("AnotherClass").statics.bar)
    
  • objectid function

    Returns String id of a given Java object. This id can be passed to heap.findObject and may also be used to compare objects for identity. For example:

    select objectid(o) from java.lang.Object o
    
  • reachables function

    Returns an array of Java objects that are transitively referred from the given Java object. Optionally accepts a second parameter that is comma separated field names to be excluded from reachability computation. Fields are written in class_name.field_name pattern.

    Examples

    • Print all reachable objects from each Properties instance.

      select reachables(p) from java.util.Properties p
      
    • Print all reachables from each java.net.URL but omit the objects reachable via the fields specified.

      select reachables(u, 'java.net.URL.handler') from java.net.URL u
      
  • referrers function

    Returns an enumeration of Java objects that hold reference to a given Java object. This method accepts optional second parameter that is a boolean flag. This flag tells whether to include weak reference(s) or not. By default, weak reference(s) are not included.

    Examples

    • Print number of referrers for each java.lang.Object instance

      select count(referrers(o)) from java.lang.Object o
      
    • Print referrers for each java.io.File object

      select referrers(f) from java.io.File f
      
    • Print URL objects only if referred by 2 or more

      select u from java.net.URL u where count(referrers(u)) > 2
      
  • referees function

    Returns an array of Java objects to which the given Java object directly refers to. This method accepts optional second parameter that is a boolean flag. This flag tells whether to include weak reference(s) or not. By default, weak reference(s) are not included. For example, to print all static reference fields of java.io.File class:

    select referees(heap.findClass("java.io.File"))
    
  • refers function

    Returns whether first Java object refers to second Java object or not.

  • root function

    If the given object is a member of root set of objects, this function returns a descriptive Root object describing why it is so. If given object is not a root, then this function returns null.

  • sizeof function

    Returns size of the given Java object in bytes, for example:

    select sizeof(o) from int[] o
    
  • retainedsize function

    Returns size of the retained set of the given Java object in bytes. Note: Using this function for the first time on a heap dump may take significant amount of time.

    The following is an example usage of the retainedsize function:

    select rsizeof(o) from instanceof java.lang.HashMap o
    
  • toHtml function

    Returns HTML string for the given Java object. Note that this is called automatically for objects selected by select expression. But, it may be useful to print more complex output. For example, to print a hyperlink in bold font:

    select "<b>" + toHtml(o) + "</b>" from java.lang.Object o
    

10.2.8.3 Selecting Multiple Values

Multiple values can be selected using JavaScript object literals or arrays.

For example, show the name and thread for each thread object

select { name: t.name? t.name.toString() : "null", thread: t } 
from instanceof java.lang.Thread t

array/iterator/enumeration manipulation functions

These functions accept an array/iterator/enumeration and an expression string [or a callback function] as input. These functions iterate the array/iterator/enumeration and apply the expression (or function) on each element. Note: JavaScript objects are associative arrays. So, these functions may also be used with arbitrary JavaScript objects.

  • concat function

    Returns whether the given array/enumeration contains an element the given boolean expression specified in code. The code evaluated can refer to the following built-in variables.

    • it - currently visited element

    • index - index of the current element

    • array - array/enumeration that is being iterated

    For example, to select all Properties objects that are referred by some static field some class:

    select p from java.util.Properties p
    where contains(referrers(p), "classof(it).name == 'java.lang.Class'")
    
  • count function

    Returns the count of elements of the input array/enumeration that satisfy the given boolean expression. The boolean expression code can refer to the following built-in variables.

    • it - currently visited element

    • index - index of the current element

    • array - array/enumeration that is being iterated

    For example, print the number of classes that have a specific name pattern:

    select count(heap.classes(), "/java.io./(it.name)")
    
  • filter function

    Returns an array/enumeration that contains elements of the input array/enumeration that satisfy the given boolean expression. The boolean expression code can refer to the following built-in variables.

    • it - currently visited element

    • index - index of the current element

    • array - array/enumeration that is being iterated

    • result -> result array/enumeration

    Examples

    • Show all classes that have java.io.* name pattern

      select filter(heap.classes(), "/java.io./(it.name)")
      
    • Show all referrers of URL object where the referrer is not from java.net package

      select filter(referrers(u), "! /java.net./(classof(it).name)")
      from java.net.URL u
      
  • length function

    Returns number of elements of an array/enumeration.

  • map function

    Transforms the given array/enumeration by evaluating given code on each element. The code evaluated can refer to the following built-in variables.

    • it - currently visited element

    • index - index of the current element

    • array - array/enumeration that is being iterated

    • result -> result array/enumeration

    Map function returns an array/enumeration of values created by repeatedly calling code on each element of input array/enumeration.

    For example, show all static fields of java.io.File with name and value:

    select map(heap.findClass("java.io.File").statics, "index + '=' + toHtml(it)")
    
  • max function

    Returns the maximum element of the given array/enumeration. Optionally accepts code expression to compare elements of the array. By default numerical comparison is used. The comparison expression can use the following built-in variables:

    • lhs - left side element for comparison

    • rhs - right side element for comparison

    Examples

    • Find the maximum length of any string instance

      select max(map(heap.objects('java.lang.String', false), 'it.count'))
      
    • Find string instance that has the maximum length

      select max(heap.objects('java.lang.String'), 'lhs.count > rhs.count')
      
  • min function

    Returns the minimum element of the given array/enumeration. Optionally accepts code expression to compare elements of the array. By default numerical comparison is used. The comparison expression can use the following built-in variables:

    • lhs - left side element for comparison

    • rhs - right side element for comparison

    Examples

    • Find the minimum size of any vector instance

      select min(map(heap.objects('java.util.Vector', false), 'it.elementData.length'))
      
    • Find vector instance that has the maximum length

      select min(heap.objects('java.util.Vector'), 'lhs.elementData.length < rhs.elementData.length')
      
  • sort function

    Sorts a given array/enumeration. Optionally accepts code expression to compare elements of the array. By default numerical comparison is used. The comparison expression can use the following built-in variables:

    • lhs - left side element for comparison

    • rhs - right side element for comparison

    Examples

    • Print all char[] objects in the order of size.

      select sort(heap.objects('char[]'), 'sizeof(lhs) - sizeof(rhs)')
      
    • Print all char[] objects in the order of size but print size as well.

      select map(sort(heap.objects('char[]'), 'sizeof(lhs) - sizeof(rhs)'), 
       '{ size: sizeof(it), obj: it }')
      
  • top function

    Returns top N elements of the given array/enumeration. Optionally accepts code expression to compare elements of the array and the number of top elements. By default the first 10 elements in the order of appearance is returned. The comparison expression can use the following built-in variables:

    • lhs - left side element for comparison

    • rhs - right side element for comparison

    Examples

    • Print 5 longest strings

      select top(heap.objects('java.lang.String'), 'rhs.count - lhs.count', 5)
      
    • Print 5 longest strings but print size as well.

      select map(top(heap.objects('java.lang.String'), 
       'rhs.count - lhs.count', 5), '{ length: it.count, obj: it }')
      
  • sum function

    Returns the sum of all the elements of the given input array or enumeration. Optionally, accepts an expression as second param. This is used to map the input elements before summing those.

    For example, return the sum of sizes of the reachable objects from each Properties object:

    select sum(map(reachables(p), 'sizeof(it)')) 
    from java.util.Properties p
     
    // or omit the map as in ...
    select sum(reachables(p), 'sizeof(it)') 
    from java.util.Properties p
    
  • toArray function

    Returns an array that contains elements of the input array/enumeration.

  • unique function

    Returns an array/enumeration containing unique elements of the given input array/enumeration.

    The following example selects a unique char[] instances referenced from strings. Note that more than one string instance can share the same char[] for the content.

    // number of unique char[] instances referenced from any String
    select count(unique(map(heap.objects('java.lang.String'), 'it.value')))
     
    // total number of Strings
    select count(heap.objects('java.lang.String'))
    

10.2.8.4 Other Examples

The following example prints a histogram of each class loader and number of classes loaded by it.

java.lang.ClassLoader has a private field called classes of type java.util.Vector and Vector has a private field named elementCount that is number of elements in the vector. The query selects multiple values (loader, count) using JavaScript object literal and map function. It sorts the result by count (i.e., number of classes loaded) using sort function with comparison expression.

select map(sort(map(heap.objects('java.lang.ClassLoader'), 
'{ loader: it, count: it.classes.elementCount }'), 'lhs.count < rhs.count'),
'toHtml(it) + "<br>"')

The following example shows the parent-child chain for each class loader instance.

select map(heap.objects('java.lang.ClassLoader'),
      function (it) {
         var res = '';
         while (it != null) {
            res += toHtml(it) + "->";
            it = it.parent;
         }
         res += "null";
         return res + "<br>";
      })

Note that the parent field of java.lang.ClassLoader class is used and the example walks until the parent is null using the callback function to map call.

The following example prints the value of all System properties. Note that this query (and many other queries) may not be stable - because private fields of the Java platform classes may be modified or removed without any notification (implementation detail). But using such queries on user classes may be safe, given that you have control over the classes.

select map(filter(heap.findClass('java.lang.System').props.table, 'it != null && it.key != null && it.value != null'),
            function (it) {
                var res = it.key.toString() + ' = ' + it.value.toString();
                return res;
            });
  • java.lang.System has static field by name 'props' of type java.util.Properties.

  • java.util.Properties has field by 'table' of type java.util.Hashtable$Entry (this field is inherited from java.util.Hashtable). This is the hashtable buckets array.

  • java.util.Hashtable$Entry has key, value and next fields. Each entry points the next entry (or null) in the same hashtable bucket.

  • java.lang.String class has a value field of type char[].

10.2.9 How to Analyze CPU Performance

This task analyzes the performance of the target application. You can choose to profile the entire application or limit the code that is instrumented by specifying filters to control the classes that are profiled.

When you run this profiling task you receive the following profiling results:

  • Time in percentage and real time for executing methods in context

  • Number of times each method is invoked in context

  • Chains of method calls leading to method invocation

  • Time / number for executing methods in context

To analyze performance of the application:

  1. Open the application you want to analyze.

  2. From the main menu, select Run > Profile project.

  3. Click CPU in the left pane of the Profile window.

  4. In the Filter list, select a filter.

  5. If you choose, you can use profiling points to control profiler actions.

  6. If you want to create a new custom configuration, click Create Custom...

  7. Click Run.

When you click Run, the target application launches and the profiling session starts.

10.2.10 How to Create a Custom Configuration

When you create a custom configuration, you have complete control over all of the available internal settings for that profiling task. You can create, store, and assign names to separate sets of custom profiling settings. The custom configuration is associated with a specific project and is selectable in the Monitor, CPU, and Memory sections of the Profile dialog.

You can set more advanced profiling options by clicking Advanced Settings. Custom configurations are automatically saved between IDE work sessions so that they can be reused and modified.

To create a custom configuration:

  1. Open the application for which you want to create a custom configuration.

  2. From the main menu, select Run > Profile project.

  3. Click Monitor, CPU, or Memory in the left pane of the Profile window.

  4. Select the options you want to be part of the configuration, for example, filters, profiling points, etc.

  5. Click Create Custom...

  6. In the Name text box, enter a name for the new configuration.

  7. Click OK.

10.2.11 Filtering Profiling Results

In the Live Profiling Results window and in result snapshots you can use the filter box located below the displayed results to filter the results by name.

To filter results by name:

  1. From the Main menu, click Window > Profiling > Live Results.

  2. Enter the filter term in the filter box below the displayed results.

    In snapshots, the filter box is available in the HotSpots and Combined tabs in CPU snapshots, and in the Memory tab in memory snapshots.

  3. Choose one of the following filtering parameters for the term from the drop-down menu:

    • Contains (case insensitive)

    • Does Not Contain (case insensitive)

    • Regular expression (case sensitive)

  4. Click the check on the right to apply the filter to the results.

You can see and select previous filter terms by clicking the arrow to the right of the filter box. To restore the full unfiltered results, click Clear Filter to the right of the filter box.

10.2.12 How to Set Profiling Filters

When you analyze application performance, you can use filters to specify the classes that you want to include or exclude in the instrumentation. When you use a filter you limit the number of instrumented classes and reduce the profiling overhead. You choose a filter by selecting a filter from the Filter drop-down list when you configure the profiling session.

To modify the Quick Filter settings:

  1. Open the application for which you want to create a custom configuration.

  2. From the main menu, select Run > Profile project.

  3. Click Show filter value under the Filter field.

  4. Click To QuickFilter in the Filter Value dialog.

  5. Select either Exclusive or Inclusive as the filter type.

  6. Enter filter values and click OK.

If you want to use a filter more than once, you can create a custom filter set.

To modify or create a custom filter set:

  1. Choose CPU in the Select Profiling Task dialog.

  2. Click Edit Filter Sets.

  3. Select an existing filter set or click Add and enter a name for the new filter set.

  4. Specify a filter set name if you are defining a new filter set.

  5. Specify the Filter Set Type.

  6. In the Global Filters list, activate the global filters you wish to be part of the filter set by selecting the checkbox for that filter.

    You can place your cursor over the values to see all the patterns included in that filter.

  7. Click OK to save the new custom filter set

After you create a new filter set, you can choose the filter in the Filter drop-down list. You can use the new filter when analyzing the performance of any project.

10.2.13 Working with Live Profiling Results

The Live Profiling Results window displays the live results of the running profiling session. You can use the toolbar and popup menus to work with the results displayed in the Live Profiling Results window. To open the Live Profiling Results window, do one of the following during a profiling session:

  • Choose Window > Profiling > Live Results from the main menu.

  • Click Live Results in the Profiler window.

Element Description
Update Results Automatically When enabled (default), results are updated at short intervals. When disabled, click Update Results Now to update the results.
Update Results Now Click to update the results immediately.
Run Garbage Collection and Update Results Run garbage collection.
Reset Collected Results Click to discard the already accumulated profiling results.
Take Snapshot of Collected Results Click to save the results as snapshot. The unsaved snapshot is opened in the Source Editor.
Export to Click to export data to the specified location.
Save Current View to Image Click to save the displayed results as a .png image.

You can sort the results by clicking on the respective column header or right-click result entries to choose commands from the popup menu. The results that are displayed and the popup menu items available depend on which of the following profiling tasks is running.

10.2.14 Profiling Using Attach Mode

However, if you want or need to start your application outside of the IDE you can use the attach mode to profile an application. For example, you may want to use the attach mode in the following cases:

  • Your application needs to be started from the command line or uses a complex launch script.

  • You want to obtain profiling data on the startup of the application or target JVM.

  • You want to profile the application without restarting the application.

You must use the attach mode in the following cases:

  • You want to profile an application running on a remote JVM, such as a remote application server.

The Attach mode enables you to attach the profiling tool to an application that is already running, or just about to start on a local or remote machine. Using the attach mode is useful for profiling long-running applications, and in particular for profiling web or enterprise applications running on top of an application server. You can also use the attach mode to profile the code of the application server itself.

Before you can attach to an application, the startup options for the target application or server need to be configured. You use the Attach Wizard to specify the attachment settings for a project. You only need to configure the attachment settings once. The attachment settings are project specific, which means that each project has its own settings. You can go through the Attach Wizard at any time if you want to modify any of the attachment settings.

In the Attach Wizard you specify the type of application and the location. Based on the details that you provide, the Attach Wizard provides you with a set of instructions on how to configure the application or server so that you can attach the profiler.

The attach mode you choose depends on the type of profiling data you want to obtain and the details of the target JVM platform. The following table provides an overview of the attach modes:

  • Local Direct

    Use this mode if you want to obtain profiling data on the startup of a local application.

    When you use this mode, the target JVM and application wait until you attach the profiler before starting. After you detach from the application, you need to restart the application to start another profiling session.

  • Local Dynamic (requires JDK 1.6)

    Use this mode if you want to obtain profiling data on a local application. To use this mode, the application needs to be running on JDK 1.6 or later.

    When you use this mode, you can attach to and detach from the application without restarting application.

  • Remote Direct

    Use this mode if you want to obtain profiling data on an application running on a remote JVM. To use this mode, you need to install the Profiler Remote Pack on the target machine. You specify the details of the remote system and generate the Profiler Remote Pack using the Attach Wizard.

    When you use this mode, the remote application starts after the profiler is attached. This mode enables you to obtain profiling data on the startup of the target JVM.

10.2.15 How to Monitor an Application

When you choose Monitor Application in the Profiling Task box, the target application runs without any instrumentation. The results show only high-level information about some properties of the target JVM, including thread activity and memory allocations.

To monitor an application:

  1. Open the application you want to monitor.

  2. From the main menu, select Run > Profile.

  3. Click Monitor.

  4. Optionally select Enable Threads Monitoring.

    Select this option to monitor threads from application startup. The option, Sample threads states, is selected by default. This option periodically updates thread states by polling the application.

  5. Click Run.

When you click Run, the target application launches and the profiling task starts. Click the Telemetry button or the Threads button in the Profiler window to view the results.

By default, application thread activity is not monitored. You can start monitoring thread activity at any time during a profiling session by opening the Threads tab and clicking the Threads button.

If you want to monitor threads from application startup, select Enable Threads Monitoring before you start the profiling session.

10.2.16 How to Set Profiling Points

A profiling point is a marker in your source code which can invoke specific profiling actions. You set a profiling point in your code by using the popup menu in the Source Editor or by using the toolbar in the Profiling Points window.

You can set the following types of profiling points:

  • Reset Results

  • Stopwatch

  • Take Snapshot

  • Timed Take Snapshot

  • Triggered Take Snapshot

Note: Icons for the Timed Take Snapshot and Triggered Take Snapshot do not display in code editors. They only display in the Profiling Points window.

You can use a profiling point to reset profiling results, take a snapshot or record the timestamp or execution time of a code fragment.

Once you set a profiling point it becomes part of the project until you delete it.

To set a profiling point:

  1. Locate the class where you want to add the profiling point and open the class in the Source Editor.

  2. In the Source Editor, right-click in the gutter on the line where you want to add the profiling point.

  3. Select Add Profiling Point to open the New Profiling Point wizard.

  4. Select a profiling point type and the project.

  5. Click Next.

  6. Customize the properties of the profiling point, if necessary.

  7. Click Finish.

An icon representing the profiling point type appears in the Source Editor where you inserted the profiling point.

To enable or disable a profiling point, in the Source Editor, right-click in the left margin of the line containing the profiling point and choose <Profiling point name> > Enable or Disable.

To view active profiling points:

  1. Open the application.

  2. From the main menu, select Run > Profile.

  3. Select a profiling task (CPU or Memory).

  4. Select Show Active Profiling Points.

You can also select Window > Profiling > Profiling Points.

10.2.17 How to Attach to a Remote Application

You can profile an application that is running on a remote system such as a web server by attaching the profiling tool to the application. When you use this mode, the remote application starts after the profiler is attached. This mode enables you to obtain profiling data on the startup of the target JVM.

To attach the profiling tool you use the Attach Wizard to specify the attachment settings for your project. In the Attach Wizard you specify the type of application and the remote location. Based on the details that you provide, the Attach Wizard provides you with a set of instructions on how to configure the remote system to support profiling.

To attach to a remote system you need to install a Remote Profiler Pack on the remote system and start the remote system on the pack. You use the Attach Wizard to specify the details of the remote system and to generate a Remote Profiler Pack for that system. See Section 10.2.18, "How to Generate a Profiler Remote Pack" for more information.

After you configure the remote system according to the instructions, you can attach the profiler to the remote location. You only need to configure the attach mode once. The attachment settings are associated with that project. You can go through the Attach Wizard at any time to change any of the attachment settings.

To profile a remote application:

  1. Open the application.

  2. From the main menu, select Run > Attach Profiler.

  3. On the Profiler dialog, click define... to configure the attachment settings.

  4. Under Attach Method, select Remote.

  5. Complete the Attach wizard to specify the attachment settings according to the target application.

  6. Click Finish to exit the Attach wizard.

  7. Configure the target location and start the remote application according to the instructions provided in the last page of the Attach Wizard. You will need to install the generated Profiler Remote Pack on the remote system if not installed.

    When you start the remote application, the application will wait until the IDE is attached before starting.

  8. In the Profiler page, select a profiling task and any profiling options.

  9. Click Attach.

When you click Attach, JDeveloper will attach to the remote JVM and the application will start. You can view profiling data as you would for a local application.

After the IDE is attached to the remote application you can do the following:

  • Detach from the remote application

    When you detach from the remote application, the remote application does not stop but you stop receiving profiling data about the remote application. To attach to the remote application you need to use the startup options provided by the Attach wizard and start the remote application again.

  • Modify the profiling session

    You can modify the profiling session without detaching from the remote application. For example, you can change the profiling task to monitoring to reduce the profiling overhead, and then modify the task again later. This way you do not need to reattach and restart the remote application.

10.2.18 How to Generate a Profiler Remote Pack

To attach the profiling tool to a remote system you need to install a Remote Profiler Pack on the remote system. The Remote Profiler Pack is an archive of libraries that enables the profiling tool to attach to the remote system.

To generate a Remote Profiler Pack:

  1. Open the application.

  2. From the main menu, select Run > Attach Profiler.

  3. At the bottom of the Attach Profiler dialog, click define...

  4. Under Attach Method, select Remote.

  5. Specify the Hostname and Operating System.

  6. Read the attach instructions and click Create a Remote Profiling Pack.

When you click Generate Remote Pack, you are prompted to specify a location where you want to save the Profiler Remote Pack. After the IDE generates the pack you need to follow the Attach Wizard instructions to install the pack and start the remote system on the pack.

10.2.19 How to Attach to a Local Application:

You can use the attach mode to profile a local application when you want or need to start the application outside of the IDE. For example, you may want to use the attach mode in the following cases:

  • Your application needs to be started from the command line or uses a complex launch script.

  • You want to obtain profiling data on the startup of the application or target JVM.

  • You want to profile the application without restarting the application (Dynamic attach mode, requires JDK 1.6).

To attach to a local application, you first need to configure the attachment settings using the Attach wizard. These settings are associated with the project you are profiling. You only need to configure the attach settings for your project once, but you can modify the settings at any time by stepping through the Attach wizard again.

When you configure the settings for attaching to a local application, you can choose from the following attachment modes:

  • Direct - This mode enables you to obtain profiling data on the startup of the local application.

  • Dynamic (requires JDK 1.6 or later) - This mode allows you to detach from and re-attach to the application without stopping the application.

To remotely attach to a local application:

  1. Open the application.

  2. From the main menu, select Run > Attach Profiler.

  3. In the Attach To list, select the project, if available.

  4. At the bottom of the Attach Profiler dialog, click define...

  5. In the Attach Settings wizard, select the Local attach mode.

  6. Complete the Attach wizard to specify the attachment settings according to the target application.

  7. Click OK to exit the Attach Settings wizard.

  8. Configure the target location and start the local application according to the instructions provided in the Attach Wizard. You will need to install the generated Profiler Remote Pack on the local system if not installed. See Section 10.2.18, "How to Generate a Profiler Remote Pack" for more information.

    When you start the local application, the application will wait until the IDE is attached before starting.

  9. Select a profiling task and any profiling options.

  10. Click Attach.

After the IDE is remotely attached to the local application you can do the following:

  • Detach from the remote local application

    When you detach from the remote local application, the application does not stop but you stop receiving profiling data about the application. To attach to the remote application you need to use the startup options provided by the Attach wizard and start the remote application again.

  • Modify the profiling session

    You can modify the profiling session without detaching from the remote application. For example, you can change the profiling task to monitoring to reduce the profiling overhead, and then modify the task again later. This way you do not need to reattach and restart the remote application.

10.2.20 How to View Thread Activity

During a profiling session, you can view detailed information about application thread activity in the Threads window.

You can start monitoring thread activity at any time during a profiling session by opening the Threads tab and clicking the Threads button. By default, application thread activity is not monitored until invoked.

To open the Threads Window:

  • From the main menu, choose Window > Profiling > Threads.

    If you want to monitor threads from application startup, select Enable Threads Monitoring when you start the profiling session. You can find this advanced setting on the Profile dialog.

10.2.21 How to View Telemetry Results

You can view high-level data on thread activity and memory heap and garbage collection in the VM Telemetry window. The VM Telemetry window is typically visible in the main Editor window.

To open the VM Telemetry window, do one of the following during a profiling session:

  • Select Window > Profiling > VM Telemetry from the main menu.

  • Click VM Telemetry in the Profiler tab (click Window > Profiling > Profiler from the main menu.

VM Telemetry results are displayed in the following tabs:

  • Memory (Heap) - This tab displays the total size and used size of the heap.

  • Memory (GC) - This tab displays the relative time spent in garbage collection and the number of surviving generations.

  • Threads/Loaded Classes - This tab displays the total number of threads in the profiled application JVM.

In each of the tabs, you can place your cursor over the graph to invoke a tooltip that displays more detailed data.

10.2.22 How to Take a Snapshot

A snapshot captures profiling data at a specific point in time. The data captured in a snapshot depends on the type of profiling session in progress when the snapshot is taken. You can explore snapshots using the toolbar in the Snapshot window and by filtering the displayed results. You can also right-click a result and select additional commands in the pop-up menu.

A snapshot differs from live profiling results in the following ways:

  • Snapshots can be examined when no profiling session is running.

  • Snapshots contain a more detailed record of profiling data than live results.

  • Snapshots can be easily compared.

You can only take a snapshot while a profiling session is in progress. You can take a snapshot manually or set a profiling point to take a snapshot automatically at a precise point in your application. When you use a profiling point to take a snapshot, you locate the point in your source code where you want to take a snapshot. For example, you may want to take a snapshot when a thread enters a specific method.

When you take a snapshot, the snapshot opens in the main editor window. You can then save the snapshot to your project.

To take a snapshot manually:

  1. Start a profiling session (for more information, see Section 10.2.3, "How to Start a Profiling Session").

  2. From the main menu, click Window > Profiling > Profiler.

  3. Click Take Snapshot.

To take a snapshot using a profiling point:

  1. Open the source file containing the line of code where you want to place the profiling point.

  2. Right-click in the gutter next to the line of code and click Add Profiling Point.

  3. Select one of the snapshot options in the New Profiling Point wizard and click Next.

  4. Modify any of the profiling point properties in the Customize Properties page of the wizard.

  5. Click Finish.

You can save a snapshot to your project or you can save the snapshot to a location on your local file system. When you save a snapshot to your project, the snapshot is listed under Saved Snapshots in the Profiler window. You can save a snapshot by clicking the Save to Project button in the snapshot toolbar. Alternatively, you can use the Tools > Preferences > Profiler window to configure the behavior when taking a snapshot.

10.3 Unit Testing with JUnit

JUnit is an open source regression testing framework for Java. Use JUnit to write and run tests that verify Java code.

Use JUnit wizards in JDeveloper to create test fixtures, cases, and suites. In addition to wizards for creating test components for generic projects, specialized wizards for business components projects are provided.

JUnit is an optional feature that can be installed and integrated with JDeveloper.

10.3.1 How to Install JUnit

JUnit is an optional feature that is not distributed with JDeveloper. You must download and install it if you wish to use it.

Note:

JUnit is provided under an IBM public license agreement. You must accept to the license agreement before downloading JUnit.

To install JUnit in JDeveloper:

  1. Navigate to Help > Check for Updates to download JUnit from the Oracle Technology Network (OTN).

  2. Exit and restart JDeveloper.

    JUnit will be installed. Use the Extension Manager if you want to uninstall it.

10.3.2 Creating a JUnit Test for a Java Project

A JUnit test application consists of the following components:

  • One or more test cases, which invoke the methods that are to be tested, and make assertions about the expected results. While test case classes generated by default have 'Test' in their names, the user can specify any valid Java name.

  • Test fixtures, which provide the state in which the tests are run. Any class can serve as a test fixture, but JDeveloper provides wizards to help you create specialized test fixture classes. While test fixture classes generated by default have 'Fixture' in their names, the user can specify any valid Java name.

  • A test suite, which invokes the test cases. Default test suite classes have 'AllTests' in their names.

  • A runner, which invokes the test suite and collates and displays the results of the tests.

10.3.3 How to Create a JUnit Custom Test Fixture

A test fixture is a set of objects, having known values, that provide data for the test cases. Any class can serve as a test fixture, but JDeveloper provides wizards to help you create custom test fixture classes and various specialized test fixture classes.

Note:

UnitTestFixture is a public class. If you create an instance of it, there will be no errors in generated code.

AppModuleAMFixture is a private class. If you create an instance of it, there will be errors in the generated code.

To create a JUnit custom test fixture class:

  1. In the Applications window, select the project.

  2. Choose File > New > From Gallery.

  3. In the Categories tree, expand General and select Unit Tests.

  4. In the Items list, double-click Test Fixture.

  5. Complete the wizard to create the test fixture class.

    The class created by the wizard will be opened for editing.

  6. Modify the file as needed.

    In particular, add code that initializes test fixture objects to the setUp() method. Add code that releases any resources they acquire to the tearDown() method.

10.3.4 How to Create a JUnit JDBC Test Fixture

A test fixture is a set of objects, having known values, that provide data for the test cases. A JDBC test fixture provides code that establishes a database connection for the test cases to use.

To create a JUnit JDBC test fixture class:

  1. In the Applications window, select the project.

  2. Choose File > New > From Gallery.

  3. In the Categories tree, expand General and select Unit Tests (JUnit).

  4. In the Items list, double-click Test Fixture.

  5. Complete the dialog to create the test fixture class.

    The class that was created will be opened for editing.

  6. Modify the file as needed. In particular, to the setUp() method add code that initializes test fixture objects, and to the tearDown() method add code that releases any resources they acquire.

10.3.5 Creating a JUnit Test Case

A test case class has one or more methods that perform tests by calling JUnit assertions. Example 10-1 shows a typical test case in JUnit 3.x. It passes test fixture data to the method being tested, and then compare the result with a known value to confirm that it is what is expected.

Example 10-1 JUnit 3.x Test Case

public void testCountChars()
{
      int expected = 4;
      int actual = fixture1.countChars('a');
      assertEquals(expected, actual);
}

Example 10-2 JUnit 4 Test Case

@Test
public void testCountChars()
{
      int expected = 4;
      int actual = fixture1.countChars('a');
      Assert.assertEquals(expected, actual);
}

In the test case shown in Example 10-2, countChars() is being tested, and the result of the test is checked by assertEquals(), which is one of a variety of assertion methods defined in the JUnit Assert class. The state of the test fixture, fixture1, is established in the setUp() method, which will have been called before the test case is called, as shown in Example 10-3.

Example 10-3 setUp() method

protected void setup() throws Exception
{
fixture1 = new StringFixture("Goin' to Kansas City, Kansas City, here I come.");
}

To create a JUnit test case class:

  1. In the Applications window, select the project or the particular class that you want to test.

  2. Choose File > New > From Gallery.

  3. In the Categories tree, expand General and select Unit Tests.

  4. In the Items list, double-click Test Case.

  5. In the Select the Class to Test page of the Create Test Case dialog, enter the class under test or click Browse.

  6. In the Class Browser dialog, locate the class you want to test or enter the beginning letters in the Match Class Name field. The Match Class list will be filtered for easier identification.

    Select the class and click OK to close the dialog. Click Next.

  7. Select the individual methods you want to test and click Next.

  8. In the Setup Test Case Class page, enter the name of the test case, the package, and the class it extends and select the list of built-in functions JUnit will create stubs for. Click Next.

  9. In the Select Test Fixtures page, select any test fixtures you want to add to the test case or click Browse.

  10. Make sure that all the test fixtures you want to add to the test case are selected in the list and click Finish.

    The class created by the wizard will be opened for editing.

You can create a test case specifically for an EJB application. For more information, see Section 28.12.3, "How to Test EJB Unit with JUnit."

10.3.6 How to Add a Test to a JUnit Test Case

You can add a unit test for a method to an existing JUnit test case class.

To add a test to a JUnit test case class:

  1. In the code editor, select a method for which you want to create a new unit test.

  2. From the main menu, choose Source > New Method Test.

  3. Select Add to Existing TestCase Class.

  4. From the Class Name dropdown box, or by using Browse, select the test case class that you want to add the new test to.

  5. To add the new test to the test case, click OK.

10.3.7 Creating a JUnit Test Suite

A test suite is a class that invokes test cases.

The JUnit Test Suite wizard has options to insert a main() method and a call to a TestRunner class. Within JDeveloper, this will open the JUnit TestRunner log window to display the test results. Edit the method if you wish to use a different test runner.

In the JUnit 3.x test suite shown in Example 10-4, the suite() method creates a TestSuite instance and adds the test cases to it. Edit this method if you wish to add or remove test cases.

Example 10-4 JUnit 3.x Test Suite

public class AllTests {
    public static Test suite() {
    TestSuite suite;
    suite = new TestSuite("project1.AllTests");
    return suite;    }        

In the JUnit 4 test suite shown in Example 10-5, the test case classes are written with @Suite and @RunWith annotations.

Example 10-5 JUnit 4 Test Suite

@RunWith(Suite.class)
@Suite.SuiteClasses( {})
public class AllTests1 {
    public static void main(String[] args) {
    String[] args2 = { AllTests1.class.getName() };
    org.junit.runner.JUnitCore.main(args2);
    }
}

To create a JUnit test suite class:

Before you create a JUnit test case, you must have created a project that is to be tested.

  1. In the Applications window, select the project.

  2. Choose File > New > From Gallery.

  3. In the Categories tree, expand General and select Unit Tests (JUnit).

  4. In the Items list, double-click Test Suite.

  5. Complete the wizard to create the test suite class. The class created by the wizard displays for editing.

  6. Modify the file as needed. In particular:

    • In the suite() method, add the test cases.

    • In the main() method, replace the runner invocation, if desired.

10.3.8 How to Create a Business Components Test Suite

The test fixture that is created is a singleton class to reduce the number of connections. If you want to connect or disconnect for each test case, customize the test case using the JUnit 4 annotations @Before and @After.

The JUnit BC4J Test Suite wizard will generate tests for each view object in the application module. If the application module does not have exported methods, the wizard will also generate a test for the application module itself. A generated view object class has the format view_objectVOTest.java and is placed into a package with the format package.view.viewobjectVO, where package is the application module package. A generated application module test has the format application_moduleAMTest.java and is placed into a package with the format package.applicationModule. A generated test fixture class has the format applicationmoduleAMFixture.java and is placed in the same package as the application module test.

The generated all test suite class has the format AllapplicationmoduleTest.java and is placed into the package with the same name as the application module package name.

A test case XML file is also generated for each application module or view object test. The XML file contains test methods defined in the application module or view object test cases. It does not include the test methods from the base classes (if any) because there may be too many duplicates.

To create a business components test suite:

  1. In the main menu, choose File and then New.

    You will create a separate project for the business components tests.

  2. In the New Gallery, expand General, select Projects and then Java Projects, and click OK.

  3. In the Project Name page of the Create Java Project wizard, enter a name and the directory path for the test project, and click Next.

  4. In the Project Java Settings page, enter the package name, the directory of the Java source code in your project, and output directory where output class files will be placed, and click Finish.

  5. In the Applications window, double-click the application module you want to test.

  6. In the overview editor, click the Java navigation tab.

  7. In the Java page, click the Edit icon for the Java Class section.

  8. In the Select Java Options dialog, select Generate Application Module Class and click OK.

  9. In the Java page of the overview editor, click the Edit icon for the Class Interface section.

  10. In the Edit Client Interface dialog, shuttle the methods you want to test to the Selected pane, and click OK.

  11. In the Applications window, right-click the test project you have created and choose New.

  12. In the New Gallery, expand General, select Unit Tests and then Business Components Test Suite, and click OK.

  13. In the Configure Tests page of the JUnit BC4J Test Suite wizard, select values for the following and click Next:

    • Business Component Project: Select the project that has the application module you want to test.

    • Application Module: Select the application module you want to test.

    • Configuration: Choose a local or shared application module.

    • Test Base Class-Application Module Extends: You can specify different base cases. The generated test case classes will extend from that base class where all public abstract methods in the base class will have simple and default implementation method bodies.

    • Test Base Class-View Object Extends: You can specify which class the view object extends. The generated test case classes will extend from that base class where all public abstract methods in the base class will have simple and default implementation method bodies.

  14. In the Summary page, verify the selections and click Finish.

10.3.9 How to Create a Business Components Test Fixture

When you create a business components test suite, a business components test fixture is created with it. You can also create Business Components test fixtures independently.

A generated test fixture class has the format applicationmoduleAMFixture.java and put into a package with the format package.applicationModule, where package is the application module package.

To create a business components test fixture:

  1. In the main menu, choose File > New > From Gallery.

    You will create a separate project for the business components tests.

  2. In the New Gallery, expand General, select Projects > Java Project, and click OK.

  3. In the Project Name page of the Create Java Project dialog, enter a name and the directory path for the test project, and click Next.

  4. In the Project Java Settings page, enter the package name and the source and output directories, and click Finish.

  5. In the Applications window, double-click the application module you want to test.

  6. In the overview editor, click the Java navigation tab and then click the Edit icon for the Java Class section.

  7. In the Select Java Options dialog, select Generate Application Module Class, and click OK.

  8. In the Java page of the overview editor, click the Edit icon for the Class Interface section.

  9. In the Edit Client Interface dialog, shuttle the methods you want to test to the Selected pane, and click OK.

  10. In the Applications window, right-click the test project you have created and choose New.

  11. In the New Gallery, expand General, select Unit Tests and then Business Components Test Fixture, and click OK.

  12. In the Configure Tests page of the JUnit BC4J Test Fixture wizard, select values for the following and click Next:

    • Business Component Project: Select the project that has the application module you want to test.

    • Application Module: Select the application module you want to test.

    • Configuration: Choose a local or shared application module.

  13. In the Summary page, verify the test fixture class and click Finish.

10.3.10 How to Update a Test Suite with all Test Cases in the Project

You update a test suite with all test cases in a project.

To update a test suite:

  1. In a class that has a suite() method, from the context menu, choose Source > Refresh Test Suite.

  2. Ensure that all items in the list of test cases are checked.

  3. To update the test suite, click OK.

10.3.11 How to Run JUnit Test Suites

When your test suite has been successfully compiled you can run it.

To run a JUnit test suite:

  1. In the Applications window, select the test suite class.

  2. Right click it, and choose Run.

    The test executes and the test runner displays the results.